i have created a bot that is runing on main.py with schedule and i have other python file (telegram.py) that receive messages trough telegram to update a flag that is my itention to start and stop the bot in main.py. How can this be achieved? I have tried so many things, but i cant access the STATUS_FLAG from my telegram.py inside my main.py, i always get 0 as value.
My telegram.py file have this content:
import requests
import logging
from aiogram import Bot, Dispatcher, executor, types
TG_TOKEN = "TOKEN"
STATUS_FLAG = 0
# Configure logging
logging.basicConfig(level=logging.INFO)
# Initialize bot and dispatcher
bot = Bot(token=TG_TOKEN)
dp = Dispatcher(bot)
#dp.message_handler(commands=['start', 'stop', 'status', 'help'])
async def send_welcome(message: types.Message):
"""
This handler will be called when user sends `/*` command
"""
global STATUS_FLAG
print(message['text'])
if message['text'] == "/start":
if STATUS_FLAG == 0:
STATUS_FLAG = 1
await message.reply("I'm going to start bot")
else:
await message.reply("Bot is already running")
if message['text'] == "/stop":
if STATUS_FLAG == 1:
STATUS_FLAG = 0
await message.reply("I'm going to stop bot")
else:
await message.reply("Bot is already stoped")
if message['text'] == "/status":
print(STATUS_FLAG)
if STATUS_FLAG == 0:
await message.reply("Bot is stopped")
else:
await message.reply("Bot is running")
if message['text'] == "/help":
text = "/start - Start the bot\n"
text += "/stop - Stop the bot\n"
text += "/status - Get bot status"
await message.reply(text)
#dp.message_handler()
async def echo(message: types.Message):
# old style:
# await bot.send_message(message.chat.id, message.text)
print(message.text)
await message.answer(message.text)
if __name__ == "__main__":
executor.start_polling(dp, skip_updates=True)
Can someone please guide me trough the correct way of doing this? Thank you so much.
I already tried to define a get function inside telegram.py and call it inside main.py
If I understand you correctly, here is the answer.
You simply return the flag to the function and output the flag where you need them.
#dp.message_handler(commands=['start', 'stop', 'status', 'help'])
async def send_welcome(message: types.Message):
"""
This handler will be called when user sends `/*` command
"""
global STATUS_FLAG
print(message['text'])
if message['text'] == "/start":
if STATUS_FLAG == 0:
STATUS_FLAG = 1
await message.reply("I'm going to start bot")
else:
await message.reply("Bot is already running")
if message['text'] == "/stop":
if STATUS_FLAG == 1:
STATUS_FLAG = 0
await message.reply("I'm going to stop bot")
else:
await message.reply("Bot is already stoped")
if message['text'] == "/status":
print(STATUS_FLAG)
if STATUS_FLAG == 0:
await message.reply("Bot is stopped")
else:
await message.reply("Bot is running")
if message['text'] == "/help":
text = "/start - Start the bot\n"
text += "/stop - Stop the bot\n"
text += "/status - Get bot status"
await message.reply(text)
return STATUS_FLAG #importantly
Do not forget to import the file
import telegram
#dp.message_handler(commands='list_wins')
async def list_wins_combo(message: types.Message):
print(await telegram.send_welcome(message)) # your file and function
await bot.send_message(message.from_user.id, 'some text', parse_mode='html')
Related
I made a number-guessing command in Discord.py. The command works perfectly fine outside of any cogs folder (main.py). Because my main.py was getting cluttered, I relocated the guess command into one of the cog's folders where I organized my other commands. When I ran the bot and try to use the guess command, I get an error saying:
loop attribute cannot be accessed in non-async contexts. Consider using either an asynchronous main function and passing it to asyncio.run or using asynchronous initialisation hooks such as Client.setup_hooktype
Below is the code I used for the guess command inside the cog:
#commands.command()
async def guess(self, ctx):
try:
await ctx.send(f"Pick a range of numbers you want and the number of attempts you want."
f"Ex: '__**1-10**, **4**__' or '__**600-10**, **200**__'")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
msg = await client.wait_for('message', check=check)
user_range = msg.content
num = re.findall(r'\d+', user_range) # get the values from the msg.content or user input
range_1 = int(num[0])
range_2 = int(num[1])
attempt = int(num[2])
if range_1 > range_2:
range_1 = int(num[1])
range_2 = int(num[0])
await ctx.send(
f"Now guess a number between **{range_1}-{range_2}**, you have **{attempt}** attempts. Type 'stop' to give up.")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
Entry = 0
ran_picker = random.randrange(range_1, range_2)
while Entry <= attempt:
msg = await client.await_for('message', check=check)
Entry = Entry + 1
if msg.content == "stop" or msg.content == "Stop":
await ctx.send(f"You gave up 😢")
await ctx.send(f"The number was **{ran_picker}**")
break
elif int(msg.content) == ran_picker:
await ctx.send(f"**Good job, it was {ran_picker}!**")
break
elif int(msg.content) > range_2 or int(msg.content) < range_1:
await ctx.send(f"Pick a number between **{range_1}-{range_2}**!")
Entry = Entry - 1
print(Entry)
elif Entry == attempt:
await ctx.send(f"You ran out of inputs, it was **{ran_picker}**!")
break
else:
await ctx.send(f"Nope, keep guessing", delete_after=2)
else:
await ctx.send(
f"Now guess a number between **{range_1}-{range_2}**, you have **{attempt}** attempts. Type 'stop' to give up.")
def check(msg):
return msg.author == ctx.author and msg.channel == ctx.channel
Entry = 0
ran_picker = random.randrange(range_1, range_2)
while Entry <= attempt:
msg = await client.await_for('message', check=check)
Entry = Entry + 1
if msg.content == "stop" or msg.content == "Stop":
await ctx.send(f"You gave up 😢")
await ctx.send(f"The number was **{ran_picker}**")
break
elif int(msg.content) == ran_picker:
await ctx.send(f"**Good job, it was {ran_picker}!**")
break
elif int(msg.content) > range_2 or int(msg.content) < range_1:
await ctx.send(f"Pick a number between **{range_1}-{range_2}**!")
Entry = Entry - 1
print(Entry)
elif Entry == attempt:
await ctx.send(f"You ran out of inputs, it was **{ran_picker}**!")
break
else:
await ctx.send(f"Nope, keep guessing", delete_after=2)
except Exception as error:
print(f"{error}")
await ctx.send(f"Problem: **[{error}]**")re
In fact, other commands that's inside a cog folder involving the function/line
msg = await client.await_for('message', check=check)
# specifically' client.await_for'
I get a similar error.
I am fairly new to Python's language and Discord.py. I tried to read some of the documents for discord.py revolving around "setup_hooktype" and try to see how I can implement it into my code. Every time I change something I get a new error saying: "unexpected keyward argument," "no attributes" and so on. I believe this function has to do with the subclass (which I have for the cog) but I'm not sure how to create an addon for "setup_hook." I could just leave this command in my main.py, but soon or later I'm going to encounter this problem again in the future.
Any help is appreciated, thanks!
I've been trying to work on a system where if you run the "AWM" command, the bot will check all further messages from anyone in a given server, if the message contains a key-phrase (in this case being 's') the bot will send "FlyingWiener go brrrrrrrrrrrrr" in the same channel as the message it found. But I don't know why my code isn't working, could I please have some help? Thanks!
def MessageContentDetection(): #on_message event definition where it detects "s" in a given message's content
#bot.event
def on_message(message):
if 's' in message.content:
await message.channel.send("FlyingWiener go brrrrrrrrrrrrr")
variables = {}
Messages = {}
#commands.command() #Activation Command
async def AWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 0:
variables[ctx.guild.id] = 1
await ctx.send("WienerMode Now Active!")
Messages[ctx.guild.id] = 1
else:
await ctx.send("WienerMode is still active Sherlock")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")
#bot.event #Message Send Event
async def on_message(ctx):
MSG = Messages.get(ctx.guild.id, 0)
if MSG==1:
MessageContentDetection()
#commands.command() #Deactivation Command
async def DWM(ctx):
User = ctx.author
Owner = ctx.guild.owner
if User == Owner:
var = variables.get(ctx.guild.id, 0)
if var == 1:
variables[ctx.guild.id] = 0
await ctx.send("WienerMode Nolonger Active!")
Messages[ctx.guild.id] = 0
else:
await ctx.send("WienerMode is still off Idiot")
else:
await ctx.send(f"Access Denied, No access granted to **{User}**")```
You don't need the MessageContentDetection function, instead you should just check the condition inside the existing on_message event itself as the event is running either way. It can be done this way instead:
#bot.event
async def on_message(message):
if Messages.get(message.guid.id, 0) == 1:
if 's' in message.content:
await message.channel.send('FlyingWiener go brrrrrrrrrrrrr')
This way, if the condition isn't true, the on_message event will be passed and no code runs inside that.
I'm making a discord bot using python that will send certain messages every few seconds. So it doesn't clutter the channel, I want it to delete the messages it last sent in the beggining of the while loop, to replace the messages with the new ones.
I don't know how to do this and any help would be greatly appreciated :)
#bot.command()
async def start(ctx):
await ctx.send("Bot Started.")
global bot_status
bot_status = "running"
while bot_status == "running":
if bot_status == "stopped":
break
time.sleep(10)
#delete
#delete
#delete
await ctx.send("test")
await ctx.send("test")
await ctx.send("test")
.send() function has a parameter named delete_after. You can use it to delete the messages after a specific time. Also, instead of using strings, you can use booleans.
#bot.command()
async def start(ctx):
await ctx.send("Bot Started.")
global bot_status
bot_status = True
while bot_status == True:
if bot_status == False:
break
await ctx.send("test", delete_after=11)
await ctx.send("test", delete_after=11)
await ctx.send("test", delete_after=11)
await asyncio.sleep(10)
Or, you can use Message.delete. For that, you have to assign the sent messages to variables.
#bot.command()
async def start(ctx):
await ctx.send("Bot Started.")
global bot_status
bot_status = True
while bot_status == True:
if bot_status == False:
break
msg1 = await ctx.send("test")
msg2 = await ctx.send("test")
msg3 = await ctx.send("test")
await asycnio.sleep(10)
await msg1.delete()
await msg2.delete()
await msg3.delete()
I am making a discord bot using discord.py. I want to make a command to purge all messages inside a channel every 100 seconds. Here is my code:
autodeletetime = -100
autodeletelasttime = 1
#client.command()
#commands.has_permissions(manage_messages=True)
async def autodelete(ctx):
global autodeleterunning
if autodeleterunning == False:
autodeleterunning = True
asgas = True
while asgas:
message = await ctx.send(f'All messages gonna be deleted in 100 seconds')
await message.pin()
for c in range(autodeletetime,autodeletelasttime):
okfe = abs(c)
await message.edit(content=f"All messages gonna be deleted in {okfe} seconds" )
await asyncio.sleep(1)
if c == 0:
await ctx.channel.purge(limit=9999999999999999999999999999999999999999999999999999999999999999999)
await time.sleep(1)
autodeleterunning = False
else:
await ctx.send(f'The autodelete command is already running in this server')
I want the loop to restart every 100 seconds after the purge is complete.
You should use tasks instead of commands for these kind of commands.
import discord
from discord.ext import commands, tasks
import asyncio
#tasks.loop(seconds=100)
async def autopurge(channel):
message = await channel.send(f'All messages gonna be deleted in 100 seconds')
await message.pin()
try:
await channel.purge(limit=1000)
except:
await channel.send("I could not purge messages!")
#client.group(invoke_without_command=True)
#commands.has_permissions(manage_messages=True)
async def autopurge(ctx):
await ctx.send("Please use `autopurge start` to start the loop.")
# Start the loop
#autopurge.command()
async def start(ctx):
task = autopurge.get_task()
if task and not task.done():
await ctx.send("Already running")
return
autopurge.start(ctx.channel)
# Stop the loop
#autopurge.command()
async def stop(ctx):
task = autopurge.get_task()
if task and not task.done():
autopurge.stop()
return
await ctx.send("Loop was not running")
In my discord bot I have some code that asks the user for input a couple of times in one command, Is there a way to have another bot command when triggered stops the current command or even forces the bot to stop running and restart entirely? Here is some of my smaller code, I would like to keep the same formatting and everything, just a command to break out of that command.
#client.command()
#commands.has_any_role("Betauri Members")
async def wsadd(ctx):
async def get_input_of_type(func):
global sentdex_guild
while True:
try:
msg = await client.wait_for('message', check=check)
return func(msg.content)
except ValueError:
continue
def check(m):
return m.content == m.content and m.channel == channel and m.author == ctx.author
channel = ctx.channel
await channel.send('type your ign, example...')
await channel.send('aaaafireball')
await channel.send('(dont retype $wslist)')
name = await get_input_of_type(str)
name = name+':'
await channel.send('type bs mods, example...')
await channel.send('bs: battery10,delta4,tw1,barrier1')
bs = await get_input_of_type(str)
await channel.send('type first support ship mods, example...')
await channel.send('miner: tw1,genesis1')
sup1 = await get_input_of_type(str)
await channel.send('type second support ship mods, example...')
await channel.send('trans: tw1,dispatch1')
sup2 = await get_input_of_type(str)
You can write your check such that it raises an exception instead of returning a falsy value when it sees certain kinds of messages:
class AbortWait(Exception):
pass
def check(m):
if m.content == 'abort':
raise AbortWait
return m.content == m.content and m.channel == channel and m.author == ctx.author
You can also handle the error in the error handler if you want special behaviour after the command has ended
#wsadd.error
async def wadd_error(ctx, error):
if isinstance(error, commands.CommandInvokeError) and isinstance(error.original, AbortWait):
await ctx.send("Command aborted")
else:
raise error
Hmm ..
What about an if statment after each step to check if the user wants to exit or not ?
Just like :
if(user_input.upper() == "QUIT"):
return