How to make the bot multithreaded? - python

I am writing a telegram bot based on OpenAI. There is a problem with multithreading. When one user asks the bot, another person can get the same information.
For example:
First user: Do you know Konstantin Polukhin?
Bot: Yes, and begins to describe it..
The second user: Do you respect him?
Bot: Yes, I know Konstantin Polukhin.
It is necessary to make sure that the data does not overlap and the bot can say something related to the request of another user.
I tried many methods that were suggested, but none helped.
Code:
from aiogram import Bot,types
import openai
import requests
from googletrans import Translator
from aiogram.utils import executor
from aiogram.dispatcher import Dispatcher
TOKEN = " "
bot = Bot(token=TOKEN)
openai.api_key = " "
dp = Dispatcher(bot)
my_list = [" ", " ", ""]
#dp.message_handler(content_types = ["text"])
async def start(message: types.Message):
#print("\n" + my_list[0] + "\n" + my_list[1])
translator = Translator()
dest_language = "en"
translated_text = translator.translate(message.text, dest=dest_language).text
my_list[2] = "\n\nHuman: " + translated_text + "\n\nAI: "
response = openai.Completion.create(
model="text-davinci-003",
prompt=f"{my_list[0] + my_list[1] + my_list[2]}",
temperature=0.5,
max_tokens=1024,
top_p=1.0,
frequency_penalty=0.5,
presence_penalty=0.0)
dest_language_2 = "ru"
translated_text1= translator.translate(text=response['choices'][0]['text'], dest=dest_language_2).text
await message.answer(translated_text1)
my_list[1] = "\n\nAI: " + response.choices[0].text
my_list[0] = "\n\nHuman: " + translated_text
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=False)```

Related

How to solve - discord.http: We are being rate limited. Responded with 429

I am creating a bot that displays Bitcoin statistics. The bot changes its activity to Bitcoin statistics every 3 seconds. But at some point the bot stops every time without error, I restart the bot and I get an error discord.http: We are being rate limited. Responded with 429. What to do, how do I need to redo the code?
import requests_html
import time
import discord
from discord.ext import commands
from discord.utils import get
from discord.ext import commands, tasks
import asyncio
intents = discord.Intents.default()
intents.message_content = True
intents.members = True
bot = commands.Bot(command_prefix='.', intents=intents)
Count = 0
#bot.command()
async def crypto_statistic(ctx):
while True:
global Count
await bot.wait_until_ready()
session = requests_html.HTMLSession()
r = session.get('https://www.coingecko.com/en/coins/bitcoin') #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
ListOfStatistic = []
#Цена
for item in r.html.xpath('/html/body/div[5]/div[5]/div[1]/div/div[1]/div[3]/div/div[1]/span[1]/span'):
Price = item.text
#Процент за 1 час
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[1]/div[3]/div[2]/div[1]/span'):
ListOfStatistic.append("1h: " + item.text)
#Процент за 24 часа
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[1]/div[3]/div[2]/div[2]/span'):
h24 = item.text
ListOfStatistic.append("24h: " + item.text)
#Процент за 7 дней
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[1]/div[3]/div[2]/div[3]/span'):
ListOfStatistic.append("7d: " + item.text)
#Процент за 30 дней
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[1]/div[3]/div[2]/div[5]/span'):
ListOfStatistic.append("30d: " + item.text)
#Процент за год
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[1]/div[3]/div[2]/div[6]/span'):
ListOfStatistic.append("1y: " + item.text)
#Лоу за 24 часа
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[3]/div[2]/div[1]/table/tbody/tr[2]/td/span/span/span[1]'):
ListOfStatistic.append("24h Low: " + item.text)
#Макс за 24 часа
for item in r.html.xpath('/html/body/div[5]/div[7]/div[1]/div/div/div/div[1]/div[1]/div[3]/div[2]/div[1]/table/tbody/tr[2]/td/span/span/span[2]'):
ListOfStatistic.append("24h High: " + item.text)
guild = discord.utils.get(bot.guilds, name="тесты") #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
member = guild.get_member(1066093484890656951) #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
if float(h24[:-1]) >= 0:
await member.edit(nick = Price + " (↗)")
else:
await member.edit(nick = Price + " (↘)")
if Count == 6:
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name = ListOfStatistic[Count]))
print(1)
Count = 0
await asyncio.sleep(3)
else:
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name = ListOfStatistic[Count]))
print(2)
Count += 1
await asyncio.sleep(3)
#bot.event
async def on_ready():
await crypto_statistic(bot.get_context)
if __name__ == "__main__":
bot.run('MyTokenHere') #!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
I tried many ways, I also looped this command through #tasks.loop and it didn't work. Some ways helped, but then my stats in bot activity which should go in that order: 1h, 24h, 7d, 30d, 1y..., went in the same order but some stats were just missing and not displayed in bot activity!
The HTTP status 429 means Too many requests, as you can see here. The Discord API has a limit to the number of requests you can make in a given time. A smart thing you can do is to intercept the status code of the response, and whether it's 429 then you do a sleep() and then redo the request!
Like so (this is a pseudo-code):
request_url = ""
request_headers = {}
response = discord_requests.get(url, headers)
if response.status_code == "429"
sleep(5)
response = discord_requests.get(url, headers)
Note that this isn't the best practice. the best practice is to know the exact amount of requests that the API can handle, calculate how many requests your script can do in that time and put a sleep()
I don't precisely know how to get the status code from the request, but through debug it should be pretty simple to understand!
Indeed, I had to do something exactly like this for a data-import script, using requests library.

How to track the change in coordinates broadcast by the user in Telegram

Telegram has a function "broadcast geolocation in real time". I need to track and display in the chat all the changes in the coordinates of the user who broadcasts his position.
I can only output current position information. Here is my code:
import data
from aiogram.utils import executor
from aiogram import Bot, Dispatcher
from aiogram.contrib.fsm_storage.memory import MemoryStorage
storage = MemoryStorage()
API_TOKEN = data.token
bot = Bot(token=API_TOKEN, parse_mode='HTML')
dp = Dispatcher(bot, storage=storage)
#dp.message_handler(content_types=['location'])
async def main(message):
await bot.send_message(message.from_user.id, "id: " + str(message.from_user.id) + "\n" +
"user: " + str(message.from_user.first_name) + " " +
str(message.from_user.last_name) + "\n" +
"date: " + str(message.date) + "\n" +
"latitude: " + str(message.location.latitude) + "\n" +
"longitude: " + str(message.location.longitude) + "\n")
if __name__ == '__main__':
executor.start_polling(dp, skip_updates=True)
How can I track the user's movement and display his new coordinates?
Great Gurus, I need your help...

Basic Voice Assistance with Python

I am a newbie in Python and I am developing a basic Voice Assistance with my teachers on Raspberry Pi 3. The code in this project is collected and fixed by me. However, as a newbie there are many questions I cant answer. Can you help me, please?
I want to develop an assistance which can search on Google, Play music on YouTube and show out the weather forecast. The AI.py is my main file, Google_Search.py is used for searching and YouTube_Search.py is used for playing music.
When I ask for searching the AI.py will import the Google_Search.py file to search for my requests. It is similar with YouTube file.
The problem is the Google_Search.py and YouTube_search.py just keep running and don't stop or allow me to keep working with the AI.py file. I want to run these two files while I still can run with the AI.py file to stop or re-open them again. These are the code, Please help me out. Thanks so much.
This is AI.py file
import speech_recognition
import pyaudio
import pyttsx3
import time
import os
import webbrowser, sys, imp
import requests, json
import vlc
import pafy
from datetime import date
from datetime import datetime
from googlesearch import search
robot_ear = speech_recognition.Recognizer()
robot_mouth = pyttsx3.init()
robot_brain = ""
api_key = "82328b3addcd3f984da6c1e74cf4c7c9"
base_url = "http://api.openweathermap.org/data/2.5/weather?"
city_name = "Melbourne,au"
complete_url = base_url + "appid=" + api_key + "&q=" + city_name
response = requests.get(complete_url)
x = response.json()
while True:
with speech_recognition.Microphone() as mic:
print("Robot: I'm Listening")
audio = robot_ear.adjust_for_ambient_noise(mic)
audio = robot_ear.listen(mic, phrase_time_limit=3)
print("Robot: ...")
try:
you = robot_ear.recognize_google(audio, language = "en")
except:
you = ""
print("You: " + you)
if you == "":
robot_brain = "I can't hear you, please try again"
elif "hello" in you:
robot_brain = "Hello Minh"
elif "play some music" in you:
import YouTube_Search
robot_brain = "Music is playing"
elif "stop music" in you:
os.system("pkill YouTube_Search")
robot_brain = "Music is stoped"
elif "search something" in you:
robot_brain = "What do you want me to search for?"
import Google_Search
imp.reload(Google_Search)
time.sleep(5)
elif "stop searching" in you:
os.system("pkill chromium")
robot_brain = "Google search is closed"
elif "weather today" in you:
if x["cod"] != "404":
y = x["main"]
current_pressure = y["pressure"]
current_humidiy = y["humidity"]
z = x["weather"]
weather_description = z[0]["description"]
robot_brain = (" Temperature: " +
str(current_temperature) + " °F" +
"\n atmospheric pressure: " +
str(current_pressure) + " hPa" +
"\n humidity: " +
str(current_humidiy) + " %" +
"\n weather today: " +
str(weather_description))
elif "bye" in you:
robot_brain = "Bye Minh"
print("Robot: " + robot_brain)
robot_mouth.say(robot_brain)
robot_mouth.runAndWait()
break
else:
robot_brain = "I'm learning"
print("Robot: " + robot_brain)
robot_mouth.say(robot_brain)
robot_mouth.runAndWait()
This is the Google_Search.py file
import speech_recognition
import os, sys
import webbrowser
robot_brain = ""
robot_ear = speech_recognition.Recognizer()
with speech_recognition.Microphone() as mic:
#print("Robot: What do you want me to search for?")
audio = robot_ear.adjust_for_ambient_noise(mic)
audio = robot_ear.listen(mic, phrase_time_limit=2)
try:
you = robot_ear.recognize_google(audio, language = 'en-US')
except:
you = ""
search_terms = [you]
# ... construct your list of search terms ...
for term in search_terms:
url = "https://www.google.com/search?q={}".format(term)
webbrowser.open_new_tab(url)
robot_brain = ("Here is what I found for") + (" ") + str(you)
print("Robot: " + robot_brain)
os.system("pkill Google_Search")
This is the YouTube_Search.py
import vlc
import pafy
import time
import urllib.request
import urllib.parse
import re
import speech_recognition
robot_ear = speech_recognition.Recognizer()
with speech_recognition.Microphone() as mic:
print("Robot: What do you want me to search for?")
audio = robot_ear.adjust_for_ambient_noise(mic)
audio = robot_ear.listen(mic, phrase_time_limit=2)
try:
you = robot_ear.recognize_google(audio, language = 'en-US')
except:
you = ""
search = you
query_string = urllib.parse.urlencode({"search_query" : search})
html_content = urllib.request.urlopen("http://www.youtube.com/results?search_query="+query_string)
search_results = re.findall(r"watch\?v=(\S{11})", html_content.read().decode())
#print("http://www.youtube.com/watch?v=" + search_results[0])
url = "http://www.youtube.com/watch?v=" + search_results[0]
video = pafy.new(url)
best = video.getbest()
playurl = best.url
Instance = vlc.Instance()
player = Instance.media_player_new()
Media = Instance.media_new(playurl)
Media.get_mrl()
player.set_media(Media)
player.play()
The import keyword in Python is used to load other Python source code files in to the current interpreter session.
When you import a file, that file will be run first. If you want to call the program in your imported file, you should use a function and call that. For example:
test.py
def myFunction():
print("Hello")
main.py
import test
test.myFunction()

TypeError: 'NoneType' object is not subscriptable | Python

I am creating a simple USPS Tracking Bot for Discord.
It works by using the !usps TRACKING NUMBER command in Discord
Here is the code:
import shippo
import discord
import asyncio
import datetime
token = 'xxxxxxxxxxxxxxxxxxxxxxxxxxxxx'
client = discord.Client()
shippo.config.api_key = "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
#client.event
async def on_ready():
print('-------------------------')
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('-------------------------')
#client.event
async def on_message(message):
if message.author.bot:
return
if message.content.startswith('!help'):
embed = discord.Embed(title="Help", description="Use `!uSps TRACKING NUMBER` to get started!", color=0x8B4513)
embed.set_author(name="USPS Tracking", url="https://www.usps.com/", icon_url="https://www.freepnglogos.com/uploads/usps-png-logo/bridgeport-apartments-usps-png-logo-2.png")
embed.set_thumbnail(url="https://www.freepnglogos.com/uploads/usps-png-logo/bridgeport-apartments-usps-png-logo-2.png")
await message.channel.send(embed=embed)
if message.content.startswith('!'):
cmd = message.content.split()[0].lower()[1:]
args = message.content.split()[1:]
packageTrack = ' '.join(args)
tracking_number = packageTrack
carrier_token = 'usps'
tracking = shippo.Track.get_status(carrier_token, tracking_number)
d1 = datetime.datetime.strptime(tracking['tracking_status']['status_date'], "%Y-%m-%dT%H:%M:%SZ")
new_format = "%m-%d-%Y" + " at " + "%H:%M"
uspsStatus = tracking['tracking_status']['status_details'] + " - " + tracking['tracking_status']['status']
uspsCity = tracking['tracking_status']['location']['city']
uspsState = tracking['tracking_status']['location']['state']
uspsZip = tracking['tracking_status']['location']['zip']
uspsDate = d1.strftime(new_format)
if uspsCity is None:
print("Unavailable")
elif uspsZip is None:
print("Unavailable")
elif uspsState is None:
print("Unavailable")
if cmd == 'usps':
embed = discord.Embed(title="Tracking", color=0x8B4513)
embed.set_author(name="USPS Tracking", url="https://tools.usps.com/go/TrackConfirmAction?tLabels={}".format(str(tracking_number)), icon_url="https://www.freepnglogos.com/uploads/usps-png-logo/bridgeport-apartments-usps-png-logo-2.png")
embed.set_thumbnail(url="https://www.freepnglogos.com/uploads/usps-png-logo/bridgeport-apartments-usps-png-logo-2.png")
embed.add_field(name="Tracking Number: ", value="{}".format(str(tracking_number)), inline=False)
embed.add_field(name="Status: ", value="{}".format(str(uspsStatus)), inline=False)
embed.add_field(name="Date & Time: ", value="{}".format(str(uspsDate)), inline=False)
embed.add_field(name="Location: ", value="{}".format(str(uspsCity) + ", " + str(uspsState) + " " + str(uspsZip)), inline=False)
await message.channel.send(embed=embed)
client.run(token)
On Line 40 the uspsCity = tracking['tracking_status']['location']['city'] I get the TypeError: 'NoneType' object is not subscriptable error. As you can see I attempted to solve it in the way I thought would work, but it still writes the error. Lists and dicts are still slightly confusing to me so that could be why I'm not getting it.
This Error means you tried to get the elements of nothing (None).
tracking = shippo.Track.get_status(carrier_token, tracking_number)
I guess this function returned None. To avoid this add for example an if statement (try/catch is also possible):
if tracking not None:
uspsStatus = tracking['tracking_status']['status_details'] + " - " + tracking['tracking_status']['status']
uspsCity = tracking['tracking_status']['location']['city']
uspsState = tracking['tracking_status']['location']['state']
uspsZip = tracking['tracking_status']['location']['zip']

Python - Twitch Bot - Sending/Receiving Whispers

I wrote a simple Python twitch bot following a video tutorial, but the tutorial didn't include whisper functionality. It can currently connect to the chat of the channel I specify, but when I try to have it send a whisper nothing happens. Here's the relevant code bits:
import socket
def openSocket():
s = socket.socket()
s.connect((HOST, PORT))
message = "PASS " + PASS + "\r\n"
s.send(message.encode('utf-8'))
message = "NICK " + USER + "\r\n"
s.send(message.encode('utf-8'))
message = "JOIN #" + CHAN + "\r\n"
s.send(message.encode('utf-8'))
return s
def sendMessage(s, message):
messageTemp = "PRIVMSG #" + CHAN + " :" + message + "\r\n"
s.send(messageTemp.encode('utf-8'))
print("Sent:" + messageTemp)
def sendWhisper(s, user, message):
messageTemp = "PRIVMSG #jtv :/w " + user + " " + message
s.send(messageTemp.encode('utf-8'))
import string
from Socket import sendMessage
def joinRoom(s):
readbuffer = ""
Loading = True
while Loading:
readbuffer = readbuffer + s.recv(1024).decode()
temp = readbuffer.split('\n')
readbuffer = temp.pop()
for line in temp:
print(line)
Loading = loadingComplete(line)
def loadingComplete(line):
if("End of /NAMES list" in line):
return False;
else: return True
I've been reading a little bit about connecting to some sort of group chat in order to make this work, but I'm confused and haven't found what I'm looking for. It seems like it should be an easy fix. Any help is appreciated.
You were very close. Where you messed up is there should not be a # in front of jtv:
def sendWhisper(s, user, message):
messageTemp = "PRIVMSG jtv :/w " + user + " " + message
s.send(messageTemp.encode('utf-8'))

Categories

Resources