When I clear the console to refresh something with
from replit import clear
def cls():
clear()
This clears the screen on a thread every 3 or so seconds but when doing that i have a input on the main thread for message inputs
def main(nick):
while True:
message = input("")
if message == "!exit":
break
else:
data = {
"message":message,
"author":nick
}
requests.post(f"{glob.serverUrl}/postMessage", json=data)
I have tried to find a fix but have not been able to find anything
Related
I have the following python code that fetches data from a remote json file. The processing of the remote json file can sometimes be quick or sometimes take a little while. So I put the please wait print message before the post request. This works fine. However, I find that for the requests that are quick, the please wait is pointless. Is there a way I can display the please wait message if request is taking longer than x seconds?
try:
print("Please wait")
r = requests.post(url = "http://localhost/test.php")
r_data = r.json()
you can do it using multiple threads as follows:
import threading
from urllib import request
from asyncio import sleep
def th():
sleep(2) # if download takes more than 2 seconds
if not isDone:
print("Please wait...")
dl_thread = threading.Thread(target=th) # create new thread that executes function th when the thread is started
dl_thread.start() # start the thread
isDone = False # variable to track the request status
r = request.post(url="http://localhost/test.php")
isDone = True
r_data = r.json()
if message.content.startswith("*run"):
ticker = message.content[5:]
try:
df = exchange.fetch_ohlcv(ticker)
await message.channel.send('Read Command: will send message if long or short opportunity arises!')
valid = True
except:
await message.channel.send('Invalid ticker')
if valid == True:
bars = exchange.fetch_ohlcv(ticker, timeframe='5m', limit=210)
df = pd.DataFrame(bars, columns=['time','high', 'low', 'open','close', 'volume'])
close = df.iloc[-1]['close']
while valid == True:
if message.content == "*stop":
valid = False
trade = strat1(ticker)
The code above is for a discord bot that a friend and I are working on for a side project. My problem is in the last few lines of the code,
while valid == True:
if message.content == "*stop":
valid = False:
When a user types in *run (ticker) in discord, the code searches through data to see whether that ticker is valid or not and then based on the response, a loop will run. During that loop, I want the user to have the option to stop it without having to turn off the bot completely, but I can't seem to get it to register the *stop command. Every time I run it, it just moves past that command completely. So, if anyone knows how to fix this, please let me know.
Thank you for reading.
What you're trying to do is to interrupt a running execution. To do it in Python, you will need to use a multiprocessing algorithm.
You can try to use the multiprocessing module,
Firstly, design a master thread that listens for command in the discord server, which you already did.
Then you would wanna put the actual service, that needs to be run after the command, in a function
def thread_worker():
bars = exchange.fetch_ohlcv(ticker, timeframe='5m', limit=210)
df = pd.DataFrame(bars, columns=['time','high', 'low', 'open','close', 'volume'])
close = df.iloc[-1]['close']
trade = strat1(ticker)
Then when a command to start is received, you can initiate a new process and run the corresponding job
newProcess = multiprocessing.Process(target=thread_worker)
newProcess.start()
When your master thread receives the kill signal
newProcess.terminate()
I'm writing a telegram bot and I want to schedule it to send an automated message every day at a specific timing, cron style. I am using apscheduler to do it but I could not get the cron function to work. The interval scheduling works fine but it is not what I want.
I don't want to execute the .py file outside because I need the telegram bot to detect user's /start message.
So what I wanted to do was to detect user's /start message and then start the scheduler. Thereafter, the bot will send a message to the user everyday 8pm night.
Cron scheduling doesn't start and I don't know why. I suspect it is because it can't run within the main thread that I am running? Any advice would be helpful! Thank you.
import time
import telepot
import json
from telepot.loop import MessageLoop
from telepot.namedtuple import ReplyKeyboardMarkup # for custom keyboard
from telepot.delegate import pave_event_space, per_chat_id, create_open
from apscheduler.schedulers.blocking import BlockingScheduler
## Load token
TOKEN = 'TOKEN NUMBER'
# The main body
class main(telepot.helper.ChatHandler): # Implement continuous dialogue with user using DelegatorBot
global counter1
counter1 = 0
global counter2
counter2 = 0
def __init__(self, *args, **kwargs):
super(main, self).__init__(*args, **kwargs)
# Initialize and create empty dictionary for storing data.
self.indicator = '0'
self.data = {} # initialize an empty dictionary for storing data.
def on_chat_message(self, msg):
content_type, chat_type, chat_id = telepot.glance(msg) # this is very important.
# Debugging
print(content_type, chat_type, chat_id)
print(msg['text'])
global counter1
global counter2
scheduler = BackgroundScheduler()
#scheduler_cron = BlockingScheduler()
# Survey function
def survey():...
return
def repeat_message():
bot.sendMessage(chat_id, text='type /survey to repeat survey.')
print("Reminder sent.")
scheduler_cron.add_job(repeat_message, 'cron', day='*', week='*', day_of_week='*', hour=20, minute=00)
# Detect start messages.
while True:
if counter2 == 11: # If survey ends AKA 11 Qns done. Restart the counters.
counter1 = 0
counter2 = 0
# once bot starts, ask user to repeat survey at a specific time of the day.
if counter1 == 0: # If survey ends or at the very beginning of using the bot.
# Start message.
if msg['text'] == '/start': # /starts initiates bot. User gets greeted with a welcome message describing what the bot will do.
bot.sendMessage(chat_id,
text='Hello there.',
parse_mode='Markdown')
scheduler_cron.start()
print("Scheduler started.")
# Start survey after initializing the bot
elif msg['text'] == '/survey': # /survey initiates survey.
print("Survey started...")
#counter1 = 0
counter1 += 1
else:
bot.sendMessage(chat_id, text='I do not recognise your message.')
msg['text'] = '' # resets msg.
# User starts survey
if counter1 == 1: # if user types /survey, counter1 +=1 and when counter1 == 1, run survey function.
survey() # starts survey
counter2 += 1
break
bot = telepot.DelegatorBot(TOKEN, [pave_event_space()(per_chat_id(), create_open, main, timeout=60),])
MessageLoop(bot).run_as_thread() # Initiates the bot on telegram. Listens for user's response. If this is stopped, the entire bot stops.
print('Listening...')
while True:
time.sleep(1)
EDIT: I found out that apscheduler's cron does not work if I have another thread running in the background as stated in their documents:
BlockingScheduler: use when the scheduler is the only thing running in your process
BackgroundScheduler: use when you’re not using any of the frameworks below, and want the scheduler to run in the background inside your application
So it means I can't use apscheduler to make my bot work. Anyone know of any cron-like alternatives that allows me to schedule my telegram bot to fire message to users at specific timings of the day? Preferably, it has to be something that works with the telegram API.
Writing a chat bot that i think needs more then 1 thread. First Main thread reads constantly the chat. From time to time I need to check the moderators which i need to get from an URL((JSON)) and provide to the main thread so he can for example ban someone but not an moderator.
First Question: How do i make a thread run every 30 secs. I dont want to pause it. I want to run it, finish after getting the moderators list and then after some time run it again.
Code of Main File:
#Requests module, which gets JSON data from an url
#To get moderators in the chat.
def secondThread():
while(True):
getModsList()
def chatReading():
#Creates socket to the twitch irc chat
s = openSocket()
#Joins a specific chat room
joinRoom(s)
while(True):
#Revieves messages from irc
derp = s.recv(8192)
derp=derp.decode('utf-8')
temp = str.split(derp, "\n")
readbuffer = temp.pop()
#Loop which prints scanned thing from twitch irc chat
for line in temp:
#Time stamp
print(time.strftime('%X'), end=" : ")
#Pings server back
pingPong(s, line)
#This just displays the message recieved more readable User:Message
try:
print(getUser(line) + " typed :" + getMessage(line))
except (IndexError, UnicodeEncodeError):
print("Not an user")
def main():
thread_1 = threading.Thread(target=chatReading, args=[])
thread_2 = threading.Thread(target=secondThread, args=[])
thread_1.start()
thread_2.start()
if __name__ == '__main__':
main()
Second file with getModList
moderators = None
def getModsList():
gotList = False
while(gotList != True):
jsonList = requests.get(CHANNEL_GROUP)
#If the jsonList status_code == 200 that means that it got the list,
#every other number is bad.
statusFlag=jsonList.status_code
if(statusFlag == 200):
gotList = True
else:
print("Failed to get mods list, trying again")
continue
jsonList=jsonList.json()
#this gets the mods list
moderators = jsonList['chatters']['moderators']
time.sleep(10)
Second question would be more an advice. How do i plan the project? Its my first more serious project and I'm having trouble see how to plan it. I want to add later more funcionality to the bot like commands for user, mods, a raffle where a user by command can join only once, and after 5 minutes a winner is chosen. Thanks in advance.
----------------------- EDIT -----------------------
I still am not sure how to get the request.form['Body'] working properly. I am likely not using this request properly, but I'm not sure how else to use it. One suggestion was make a listener, but am not sure where to start on that.
So I guess now its:
1) where am I totally buggering up?
2) Any suggestions on how to make a listener?
Here's a skeleton of my set up:
from flask import Flask, request, redirect
import twilio.twiml
from twilio.rest import TwilioRestClient
from sys import exit
twil_number = "XXXXXXXXX"
sid = "XXXXXXXXXXXXXXXXXXXX"
token = "XXXXXXXXXXXXXXXXX"
tos = "XXXXXXXXXX"
client = TwilioRestClient(sid,token)
app = Flask(__name__)
#app.route("/", methods=['GET', 'POST'])
##### get the SMS ####
def smsGet():
try:
action = request.form['Body']
except RuntimeError:
action = raw_input("> ")
return action.lower()
### Snd the SMS ####
def smsSend(bods):
client.sms.messages.create(to=tos, from_=twil_number, body= bods)
class TestClass(object):
def doStuff(self):
smsSend("Intro Text")
## I don't know why this is buggering up. ###
go = smsGet()
if go == "yes":
smsSend("yes")
exit(1)
else:
pass
exit(1)
a = TestClass()
a.doStuff()
#### running the app ###
if __name__ == "__main__":
app.run(debug=True)
----------------------- older -----------------------
I'm making a text adventure game in twilio/python. There's no database or anything, Its just a python based text adventure that I run locally out of a shell.
All the sending SMS things are fine, but how do I get something like this:
request.form['Body'].lower()
to work like this:
raw_input("> ").lower()
So far most things I've tried just have Flask throwing this error:
RuntimeError('working outside of request context')
So for context. A lot of my scenes are set up like this:
class Hallway(Scene):
def enter(self):
hall = "You pause in the Hallway. You could: Go to the bedroom. Go to the kitchen to see if there's food. Check on your human in the office."
send_sms(hall)
#action = raw_input("> ").lower()
#would like this to work like raw _input()
action = request.form['Body'].lower()
if action == "kitchen":
return 'kitchen'
elif action == "bedroom":
return 'bedroom'
elif action == "office":
return 'office'
else:
nope = "But I don't want to hang in the hallway..."
send_sms(nope)
return 'hallway'
And send_sms() is just this:
def send_sms(bods):
client.sms.messages.create(body=bods,to=tos,from_=froms)
Any suggestions on where I'm totally mucking up?
Thanks! :)
So, if I understand what you're trying to do correctly, you probably want something like this (note that I haven't run this, so it may have some small bugs, but the idea should be sound):
listener.py
from flask import Flask, request
from twilio.rest import TwilioRestClient
import twilio.twiml
import game
account_sid = "ACXXXXXXXXXXXXXXXXX"
auth_token = "YYYYYYYYYYYYYYYYYY"
twilio_client = TwilioRestClient(account_sid, auth_token)
app = Flask(__name__)
games = {}
#app.route("/", methods=['GET', 'POST'])
def accept_response():
from_number = request.values.get('From')
body = request.values.get('Body')
try:
games[from_number].queue.put(body)
except KeyError:
games[from_number] = game.Game(twilio_client, from_number, "your number goes here")
games[from_number].start()
return str(twilio.twiml.Response())
if __name__ == "__main__":
app.run(debug=True)
game.py
import queue
from threading import Thread
class Game(Thread)
def __init__(self, twilio, to_number, from_number):
Thread.__init__(self, name=to_number)
self.twilio = twilio
self.from_number = from_number
self.to_number = to_number
self.queue = queue.Queue()
def run(self):
# Game logic goes here, e.g.:
action = self.send_sms("You're being chased by a thing!", wait_for_response=True)
if action == "stop":
self.send_sms("That was silly. The thing eats you, you die.")
elif action == "run":
self.send_sms("You're too slow! The thing eats you, you die.")
else:
self.send_sms("I don't know what you're trying to do, but the thing eats you, you die.")
def send_sms(self, body, wait_for_response=False):
self.twilio.messages.create(body=body, to=self.to_number, from_=self.from_number)
if wait_for_response:
response = self.queue.get()
return response
So, you run the listener, and with the correct configuration on the Twilio side it just sits there and listens for SMSs. When it receives one it checks to see if a game is already running for the user. If so, it sends the body of the SMS to the game, to be used as input. Otherwise, it kicks off a new game for that user.
Each Game instance is running in it's own thread, and you can use the send_sms method of a Game instance just like raw_input, that is, the user for that game will receive the string argument as an SMS, and their reply will be the return value.
I don't know what the rest of your game logic looks like, but to integrate this with something like the Scene class in your question, you would probably want to have Scene's consructor take a Game as an argument and assign it to an attribute. So, then, in enter() you could write something like action = this.game.send_sms('foo').
It appears you can get the current thread object using threading.current_thread() (which in this case is the Game instance), so there's no need to pass it around. You can either call threading.current_thread().send_sms from anywhere, or wire it up in the constructor of your scenes.
If you want to run that code from either inside Flask or from the command line, you'll need to write a function which will get the action, either from the request or using raw_input. It could look something like this:
from flask import request
def get_action():
try:
action = request.form['Body']
except RuntimeError:
action = raw_input("> ")
return action.lower()