Using user messages in the aiogram telegram bot function - python

In my bot, the user has to enter the date of birth, then I have to transfer this date into a set function, the result of which is later inserted as an index into a list, from where the corresponding image will be sent to the user.
Now I will show you a part of the code, it's an example of both the handler and the function, through which I want to run the user's message. As long as you use a randomly generated number and not the result from the function, everything works perfectly. The thing is that I need exactly the result you get through the calculations and for that I need to insert the message sent by the user into a variable, so that you could continue working with it - and that's exactly what I fail to accomplish.
The Question: how do you assign the user’s message to a variable in aiogram in order to further interact with it?
#dp.message_handler(commands=['start'])
async def begin(message: types.Message):
await bot.send_message(message.from_user.id, f"{text1}")
#dp.message_handler()
async def datarozh(message: types.Message):
if message.text[2] == '/' and message.text[5] == '/' and len(message.text) == 10:
await bot.send_message(message.from_user.id, f"blablabla", reply_markup=mainmenu)
elif message.text == 'Begin':
chatid = message.from_user.id
arkankart = InputFile(path_or_bytesio=f"{img_list[result_def]}") # this is where you need to substitute the value from the function after processing the user's message
await dp.bot.send_photo(chat_id=chatid, photo=arkankart, caption='blablabla')
data = "11/11/2011" # the plan is to use the user's message instead of data
s = data.split('/')
lisst = []
for i in s:
lisst.append(int(i))
def day(a): # I have several different variations of the functions through which I would run the user's message, here's one of them
result = 0
while a[0] != 0:
b = a[0] % 10
result += b
a[0] = a[0] // 10
return result

You can use function message.text to check the user's message.
#dp.message_handler()
async def send_answer(message: types.Message):
if message.text == "Test1":
print("Cool!")
So if you would to assign user's message to a variable:
#dp.message_handler()
async def send_answer(message: types.Message):
your_variable = message.text
if your_variable == "Test1":
print("Cool!")

Related

Can't pass value from one function to another. aiogram | FSM

Can't pass value from one function to another
i am using aiogram and FSM to pass
data['start_name2'] = message.text
from one function to another
who can tell me what is my mistake?
This function creates a state in the "Start" state group with the name "start_name2".
class Start(StatesGroup):
start_name2= State() #NAME
This is a telegram bot function that handles a callback query with the data 'NAME'. When triggered, the bot will send a message to the chat asking the user to write their name. The input name is then processed and sent to a GET API request, and the received information is then parsed and displayed in a limited form as messages in the chat. If the input name is invalid, the bot will send a message saying so. The function also adds a message with a link to a website at the end.
#dp.callback_query_handler(lambda c: c.data == 'NAME')
async def process_callback_button2(callback_query: types.CallbackQuery, state: FSMContext):
await bot.answer_callback_query(callback_query.id)
await bot.send_message(callback_query.message.chat.id, text='Please write name. Example : Alex Bortin',reply_markup=kb.inline_kb4)
await Start.start_name2.set()
try:
await callback_query.message.delete()
except Exception as exception:
print("someone click button")
#dp.message_handler(state=Start.start_name2)
async def namee(message: types.Message, state: FSMContext):
# Check if the input is valid
if not is_valid_input2(message.text):
await bot.send_message(message.from_user.id, "Invalid input. Please enter a valid name.")
return
name = message.text
async with state.proxy() as data:
data['start_name2'] = message.text
try:
msg = await bot.send_message(message.from_user.id, parse_mode="HTML" ,text=f'Entered name: <b>{name}</b>\n\nSearching...')#---
await bot.send_chat_action(message.from_user.id , ChatActions.TYPING)#---
for i in range(3):#---
random_emojis = random.sample(emojis, 4)#---
random_emojis_string = " ".join(random_emojis)#---
await asyncio.sleep(0.4)
await msg.edit_text(parse_mode="HTML" ,text=f'Entered name: <b>{name}</b>')#---
URL = "API"
URL2 = "JUST URL"
# GET
response_text = await fetch(URL)
soup = BeautifulSoup(response_text, "html.parser")
nameD = (soup.prettify())
print(nameD)
await msg.edit_text(parse_mode="HTML" ,text=f'Entered name: <b>{name}</b>') #---
pattern_value = r'"value"\s*:\s*(\d+),'
obj = json.loads(nameD)
data2 = ""
match_address = re.search(pattern_value, nameD)
if match_address:
value = match_address.group(1)
data2 += f'Data found: <b>{value}</b>\n'
else:
data2 += 'Data found: <b>0</b>\n'
count = 0
for index in obj['hits']['hits']:
if count >= 10:
break
count += 1
db_name = index['_index']
strings = set()
for a, b in index['_source'].items():
strings.add(f"<b>{a}</b> : {b}")
string = "\n".join(list(strings))
await bot.send_message(message.from_user.id, text=f"<b>data base name</b> : {db_name}\n{string}", parse_mode="HTML")
await message.reply('Page 0', reply_markup=get_keyboard(0))
text2 = hlink('website', URL2)
await bot.send_message(message.from_user.id, parse_mode="HTML" , text=f'\nThe report can be viewed on our WEB {text2}')
name = 0
except Exception as exception:
name = 0
text2 = hlink('website', URL2)
await bot.send_message(message.from_user.id, parse_mode="HTML" , text=f'\nThe report can be viewed on our WEB {text2}')
await state.finish()
This function is a callback handler for a callback query in the Telegram Bot API. It handles a vote "up" action, increasing the vote count by 1. It logs the callback data and retrieves a value from the state proxy (stored data). It also prints the retrieved value.
#dp.callback_query_handler(vote_cb.filter(action='up'))
async def vote_up_cb_handler(query: types.CallbackQuery, callback_data: dict, state: FSMContext):
logging.info(callback_data)
amount = int(callback_data['amount'])
amount += 1
async with state.proxy() as data:
start_name2 = data.get('start_name2')
print(start_name2)
#Here I try print start_name2
The maximum that I have achieved is that my last function outputs
"None"

Discord.py: Bot Keeps Writing Previous Values

So, I have a command that should give me an image and after that bot should ask whether user wants to keep it or not (I use thumbs-up reaction for the answer). If user reacts with 'thumbs-up', then bot says 'Saved!' and actually save the image URL to a .txt file. The problem is if user doesn't react with thumbs up and after that types command again and save this latest image, bot saves previous ones too. I use Replit for hosting. Here is the code block that doesn't work as expected:
#bot.command()
async def myfunc(ctx):
... # here goes the message attributes, requests (no problem with the requests)
thumb_up = "👍"
thumb_down = "👎"
imagesList = []
await message.add_reaction(thumb_up)
userDict = {}
n = 0
while True:
try:
reaction, user = await bot.wait_for("reaction_add", timeout=30)
if user not in userDict:
userDict[user] = 0
if userDict[user] == 0:
if (str(reaction.emoji) == thumb_up and user != bot.user):
imagesList.append(url)
fileWrite = open(f"data{user}.txt", "a")
fileWrite.write(f"{url} \n")
fileWrite.close()
await ctx.send("Saved!")
userDict[user] += 1
imagesList.clear()
except:
pass
imagesList.clear()
#bot.event
async def on_reaction_add(reaction, user):
embed = reaction.message.attachments
emoji = reaction.emoji
if emoji == ":thumbsup:":
await reaction.channel.send(embed)
It shouldn't save previous URL's to users file. It should save only URL's that the user reacted with 'thumbs-up'. I use dict to avoid that but didn't work.
Okay, so I am not much familiar with discord.py and have no clue why it writes multiple times, but I think the problem is if the message id that the user reacted is the message user reacted, I mean if there are multiple lines get written, we should discard or not to use previous of them. That's why I created a check function:
msgId = message.id
def check(reaction, user):
if user != bot and reaction.emoji == thumb_up and reaction.message.id == msgId :
return True
else:
return False
userDict = {}
while True:
reaction, user = await bot.wait_for("reaction_add", check=check, timeout=30)
if(user.id not in userDict.keys() and user.id != <id of bot>):
userDict[user.id] = 0
if(reaction.emoji == thumb_up and user.id != <id of bot> and userDict[user.id] == 0 ):
userDict[user.id] = 1
fileWrite = open(f"data{user}.txt", "a")
fileWrite.write(f"{url} \n")
fileWrite.close()
await ctx.send(f"Saved {user}")
userDict[user.id] = 1

Python If its same output dont send msg

I made a discord bot that sends every 120 sec transactions from one ethereum addrs but i dont want to send same stuff over and over so if it send USDT token and Again in 120 sec try USDT to just skip it until it got new thing is that possble or not?
code:
import requests
import sys
import json
import discord
import time
btoken = "mytoken"
result=requests.get('https://api.ethplorer.io/getAddressHistory/0x3f5ce5fbfe3e9af3971dd833d26ba9b5c936f0be?apiKey=freekey&type=transfer')
result.status_code
result.text
result.json()
results = "soon:tm:"
def price_of_gas(inp):
def recursive_function(inp):
if type(inp) is list:
for i in inp:
ans = recursive_function(i)
if ans!=None: return ans
elif type(inp) is dict:
if 'name' in inp: return inp['name']
for i in inp:
ans = recursive_function(inp[i])
if ans!=None: return ans
else: return None
ans = recursive_function(inp)
return ans if ans else "Could NOT find the new token tx"
print (price_of_gas(result.json()))
class MyClient(discord.Client):
async def on_ready(self):
print('Logged on as', self.user)
async def on_message(self, message):
# don't respond to ourselves
if message.author == self.user:
return
if message.content == '.get':
await message.channel.send('Alert! Alert! Buy')
await message.channel.send(result.json()['operations'][0]['tokenInfo']['symbol'])
await message.channel.send(result.json()['operations'][0]['tokenInfo']['address'])
print ('get command was tryed')
else:
print ('comand not found')
if message.content == '.help':
await message.channel.send("try .get")
print ('help command was tryed')
if message.content == '.stop':
await message.channel.send('Bye...')
print('bye')
sys.exit()
if message.content == '.start':
while True:
# Code executed here
print ('done')
price_of_gas(result.json())
print (price_of_gas(result.json()))
await message.channel.send(price_of_gas(result.json()))
time.sleep(120)
#print(result.json()['operations'][0]['tokenInfo']['name'])
#print(result.json()['operations'][0]['tokenInfo']['symbol'])
#print(result.json()['operations'][0]['tokenInfo']['address'])
#print (result.json()['tokenSymbol'])
#print (result.text)
print ('done no errors')
print ('done no errors with check data')
client = MyClient()
client.run(btoken)
print ('done no errors 2')
so if user type .start bot will start while loop that sends newest tx from selected addrs but problem is it will send same stuff i just need some if statment in while loop or something.
You shoudn't use the requests module (it's blocking), you should use aiohttp instead
You also shoudn't use time.sleep as it also blocks the whole thread. You should use asyncio.sleep. (If you still stay with time.sleep you're not going to be able to use the bot when it's "sleeping")
Answering your question, you can simply have a variable with the value of the previous price/value and check if the new message is the same, if it's not - send it
while True:
price = price_of_gas(result.json())
# Checking if the `previous_price` var exists
if hasattr(self, "previous_price"):
# If yes, comparing the values
if self.previous_price != price:
# If they're not the same, send the message
await message.channel.send(f"Current price: {price}")
self.previous_price = price # Updating the variable
else:
# If the `previous_price` var doesn't exists, creating it
self.previous_price = price
await asyncio.sleep(120) # Remember to import asyncio
Making HTTP requests with aiohttp
import aiohttp
async def main():
async with aiohttp.ClientSession() as session:
async with session.get("URL") as resp:
data = await resp.json()
# Note: you should create ONE session per application
EDIT:
If you want to use blocking functions (like the price_of_gas) you can use the next method
await self.loop.run_in_executor(None, price_of_gas, result.json())
More info here

Discord bot won't take in a new message

So I'm making this weird kinda discord bot. It displays a set of obstacles, and adds a corresponding key that you need to press to a string. It adds a 'w' for every '...', and an 's' for every '***'. In Discord, the player has to type the correct string in to pass the level. So it all works and displays properly. The call function is '!go', and that displays the level. But it fails me before I can type in the string. I want to know, why is it automatically activating? My message.content function is outside that loop. I think it is because I type '!go' and it doesn't reset my message. Here is the code:
#client.event
async def on_message(message):
global correct_answerS
correct_answerS = ""
obstacleList = []
for i in range (0, 24):
randNum = random.randint(1,2)
if randNum == 1:
obstacleList.append('...')
correct_answerS += 'w'
if randNum == 2:
obstacleList.append('***')
correct_answerS += 's'
if message.content == ('!practice'):
sky = str("```css\n A ... ... *** ...```")
skyembed = discord.Embed(title="!============================!")
skyembed.add_field(name='When you see three dots, it is a w. When you see 3 asteriks, it is an s.', value = sky)
await message.channel.send(embed=skyembed)
if message.content == ('wwsw'):
await message.channel.send("Success.")
if message.content == ('!go'):
randlev = (str("```css\n A "))
for i in range(0, 24):
randlev += (str(obstacleList[i]) + " ")
randlev += "```"
randlevembed = discord.Embed(title="!===============================================!")
randlevembed.add_field(name='Good luck!', value = randlev)
await message.channel.send(embed=randlevembed)
print(correct_answerS)
if message.content == (correct_answerS):
await message.channel.send("Success!")
else:
await message.channel.send("Fail.")
#client.event
async def on_ready():
print("Ready")
print(client.user.id)
print('--------------------------')
await client.change_presence(activity=discord.Game(name='up and away'))
client.run(Token)
There is no error message, just as soon as I type '!go', it displays the level and then continually says 'Fail.' until I stop it.
I don't know what to do, any help is just that, helpful. Thanks.
The bot is stuck in a loop where it's sending a message, and then processing that message, which causes it to send another message, etc. You can add a check to the beginning of on_message to force it to ignore bot-generated messages:
#client.event
async def on_message(message):
if message.author.bot:
return
...

Function to print 4x4 emote grid in a discord chat

New python-enthusiast here.
I am currently making a discord bot that responds with 16 pictures in a 4x4-grid when a specific user types in the chat:
XXXX
XXXX
XXXX
XXXX
This is my current code:
import discord
from secrets import TOKEN
from emotes import *
# user IDs
bonvang_ID = "417010736988946444"
djursing_ID = "124806046568022016"
jonathan_ID = "151788707760832512"
alex_ID = "151745760935936001"
snuffles_ID = "221360712222507009"
# bot = commands.Bot(command_prefix='!')
client = discord.Client()
# prints message in terminal when bot is ready
#client.event
async def on_ready():
print(f"Logged in as {client.user}")
# #client.event
# async def on_member_join(member):
# await message.channel.send(f"""Welcome to the server {member}!\n
# I'm just a simple bot made by Mr.Nofox.\n
# If you want to know more about the commands, ask him or try your luck with the others! :)""")
def member_amount():
# create a variable that contains all the servers
active_servers = client.servers
# create a variable to store amount of members per server
sum = 0
# loop through the servers, get all members and add them up, this includes bots
for s in active_servers:
sum += len(s.members)
return sum
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n)
#client.event
async def on_message(message):
# print(f"{message.channel}: {message.author}: \"{message.content}\"")
guild = client.get_all_members()
if "!count()" == message.content:
await client.send_message(message.channel, f"```py\nTotal members: {member_amount()}```")
elif "!report()" == message.content:
online = 0
idle = 0
offline = 0
for member in guild:
if str(member.status) == "online":
online += 1
if str(member.status) == "offline":
offline += 1
if str(member.status) == "idle" or str(member.status) == "dnd":
idle += 1
await client.send_message(message.channel, f"```Online: {online}\nIdle/busy.dnd: {idle}\nOffline: {offline}```")
#TODO: Make a neat function for the pictures in message that responds with 4x4 image in chat when a given user types
if (message.author.id == alex_ID or message.author.id == snuffles_ID):
await client.send_message(message.channel, "DET ER MIN SØN!")
await client.send_message(message.channel, picture_grid())
# add bot-token found on website
client.run(TOKEN)
All the emotes are in a file called "emotes.py" which I import.
Each emote is a string-code, example:
pic01 = '<:1_:543049824644235265>'
The line I am using to get this to work atm. is:
await client.send_message(message.channel, f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This is awful coding practice and therefore I want to make a function that returns:
f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n"
My initial thought was something like:
def picture_grid():
return (f"{pic01} {pic02} {pic03} {pic04}\n{pic05} {pic06} {pic07} {pic08}\n{pic09} {pic10} {pic11} {pic12}\n{pic13} {pic14} {pic15} {pic16}\n")
This does the trick and converts the first code to:
await client.send_message(message.channel, picture_grid())
But merely moves the bad code to another place.. I am currently stuck by what should be a simple task.
Any ideas?

Categories