Discord Bot sending messages if function is true - python

Thats my function what checks broadcast
def broadcast1():
if 'isLiveBroadcast' in contents:
return True
And thats my function what must send messages to specific text channel about broadcast
#bot.event
async def broadcast2(broadcast1):
if broadcast1 is True:
channel = bot.get_channel(1067083439263727646)
await channel.send('ЖАБА СТРИМИТ')
I have been written two functions which must work together and sends messages in text channel when broadcast is live but they dont work
No Errors, just doesnt working

There's quite a few fundamental issues with your code and the program logic.
Firstly, #bot.event is typically used for registering "listeners" to Discord events. There is no broadcast2 event to listen out for. Therefore, the function will never be executed. You can look at the event reference here and see all the events that we can respond/react to.
Secondly, as the commenter above as pointed out, you've not actually invoked the function. Saying if broadcast1 is Truedoesn't work how you think it works. By itself,broadcast1is a function, and thereforebroadcast1is a function object. It will never equal True; so event if we were listening for the right event, it would never do what you want it do anyways. What we _should_ be doing, is actually invoked the function:broadcast1()`. This means the function and the code gets run. There's lots of tutorials online about how functions in python work. Linked is just one example.
Thirdly, in the broadcast1 channel, you're checking if "isLiveBroadcast" is in contents. What contents? Where is that defined? You might need to rethink that as well.
All in all, you should probably look at following a Python basics course and then following some tutorials for putting together Discord bots. The docs are a good place to start - trying following the quickstart stuff and then adapting as you go along.

Related

Is there any way to make a command both text-based and slash-based in Pycord?

I've made a music bot in Pycord, and I want to make the commands both slash and text-based. I've implemented slash commands using discord.Bot in a cog and used the slash_command decorator.
All the code of the music bot can be seen here (the main_slash.py file contains the cog)
I have some hint that discord.ext.commands.Bot can be used, but well, to say the least, I am bewildered and perplexed in this context on using this class in my code.
I have tried these things:-
Using discord.ext.commands.Bot, but this ended up in failure (as mentioned before).
(current method, but inefficient I guess) Running two instances of the bot parallelly, with one implementing slash commands, while the other implementing text-based commands.
Bridges exist on Pycord now and you can just do:
#bot.bridge_command()
async def hello(ctx):
await ctx.respond("Hello!")
and it'll be both a text-based and slash-based command.
I suggest creating a seperate async function and then the slash command an prefixed command call that separate async function.
discord.ext.commands.Bot supports slash commands and prefix commands please read the docs

Call a python function on button click in discord_components (python)

I am making a bot in discord.py, and I want to call a function inside the code whenever someone presses a button. I looked at the documentation of discord_components(lib for buttons and select menus), but it's either I'm stupid or the documentation is bad. I also googled it but didn't find anything.
So is it possible to run a function on the interaction event?
#bot.event
async def on_button_click(interaction):
your_func()
You can just go with the flow. Be careful not to forget to send a callback.
Here is the link to the event examples on the discord components github: examples.

Check if Discord bot is online

I'm trying to make it so that only one instance of my bot can connect to Discord at a time and that the other connects only if the other one isn't connected. How could I achieve this? I'm using Discord.py. Also, if possible, I'd like it to work across multiple machines.
If you're asking what I think you're asking, that is, the bot should only be allowed to have one version of itself running on the machine at any one time, then this should work for all cases where you only want to have one of a script running at once.
One way we can do this is by having the script create a "lock" file, and exiting if said file already exists. Just remember to delete it when we're finished, even if the bot crashed.
(There are likely better ways to handle errors here and your bot code itself should do its best to handle errors that the bot may generate. For the most part discord.py will just keep going even when there are errors. This will just get the serious bot-crashing stuff and makes sure you can see what happened, while still gracefully closing and ensuring the lock file is deleted.)
import discord
from discord.ext import commands
import os # for file interactions
import traceback
# etc.
bot = commands.Bot(description="Hard Lander's lovely bot", command_prefix="!")
#bot.event
async def on_ready():
print("I'm ready to go!")
print(f"Invite link: https://discordapp.com/oauth2/authorize?client_id={bot.user.id}&scope=bot&permissions=8")
def main():
bot.run("TOKEN")
if __name__ == '__main__':
running_file = "running.txt"
if os.path.isfile(running_file): # check if the "lock" file exists
print("Bot already running!")
exit() # close this instance having taken no action.
else:
with open(running_file, 'w') as f:
f.write("running")
try: # catch anything that crashes the bot
main()
except: # print out the error properly
print(traceback.format_exc())
finally: # delete the lock file regardless of it it crashed or closed naturally.
os.unlink(running_File)
A simple way to do this to run the second bot after the bot.run() in the first bot.
Why? Because of the fact that it's blocking any other code that comes after it unless the bot stopped.
so I would suggest this:
bot.run("Your first bot token here")
import secondbot # you may use another method to run the bot script
Another way to do this is to make a third script for the second bot, this script will run periodically to check the first bot status (in this case, offline status), if the first bot status is offline, it will turn on the second bot. I'm not recommending this method for your case because you may want to change your first bot presence to offline which will make the third script think the bot goes offline.
Edit: After writing this answer I found a method of Bot called "is_closed" wich return bool wether or not the bot connected to the websocket, the link is here

Run a function which will end only after user runs a certain command

I'm creating a Discord bot to play poker. I've a function wait_for_betting_to_end which is defined like this:
def wait_for_betting_to_end():
while not_all_players_have_bet():
pass
I've a command poker inside a cog which contains the following code fragment:
#commands.command(name='poker')
async def poker(self, ctx):
self.game_started = True
# ...
await preflop()
wait_for_betting_to_end()
# ...
I've a Discord command bet inside a cog:
#commands.command(name='bet')
async def bet(self, ctx, amt):
if not self.game_started:
print("You're not playing a game.")
return
# does something that would make wait_for_betting_to_end stop
The problem is that the user is never able to run the bet command while playing poker; the execution flow remains stuck in wait_for_betting_to_end forever. While not playing, bet correctly displays the error and exists.
How can I fix this?
The problem with your code is that you make an infite loop in your wait_for_betting_to_end() function. This is a mistake stemming from the thought that discord.py uses multithreading to get its asynchronous functionality(I can guess that much looking at the tags), however it doesn't. asyncio works in a single thread, where it does a task (like receiving a message, processing a command, etc) and does the next task on completion of that one, the power of asyncio stems from the ability to temporarily 'freeze' a task when no progress can be made (like waiting for a response or just plain sleeping) to continue on to the next task, and resuming the frozen task when it needs to. (I'm pretty sure 'freezing' is completely wrong terminology btw). Every command that your bot gets is handled in its own task. You making the infinite loop never release the poker task, so it's blocking the whole loop.
To fix your problem there are a few possibilities, like:
Instead of just infinitely looping, call await asyncio.sleep(0.1) instead of pass in your loop, this will allow your bot to get messages from discord in that time, and thus react to responses from your users. To stop your while loop you could use a self.value which you set to False when it needs be(in your bet command) (maybe use something like a dictionary with games for this as you probably want to run different games at the same time).
I don't really work with cog so I can't confidently give you a worked out example how you could do your code (at least not without risking missing some thing that can easily be done with cogs). But this should put you on the right path I believe.

Python XCHAT API question

I am writing a script in XCHAT and from reading other scripts I notice use of return xchat.EAT_ALL in most of them. Here is what the documentation for the XCHAT Python API says:
Callback return constants (EAT_)
When a callback is supposed to return one of the EAT_ macros, it is able control how xchat will proceed after the callback returns. These are the available constants, and their meanings:
EAT_PLUGIN
Don't let any other plugin receive this event.
EAT_XCHAT
Don't let xchat treat this event as usual.
EAT_ALL
Eat the event completely.
EAT_NONE
Let everything happen as usual.
Returning None is the same as returning EAT_NONE.
I am wondering why to do this. I really don't understand what this is saying and there isn't that much documentation for the XCHAT Python API. I am curious as to when to use which one of these.
Just from what you've pasted in:
Certain events occur in XChat, which you can register a function to handle. It is possible for there to be more than one callback function registered for each event - either by plugins or by XChat itself.
So after your function has done whatever it wants to do, it needs to decide whether to allow other callbacks to be triggered as well. As a simple example, let's say you're writing a script which filters incoming messages that have certain words. It's triggered whenever a message is received, and goes something like:
if any(word in swearwords for word in message):
return xchat.EAT_ALL # The 'message received' event stops here
else:
return xchat.EAT_NONE # Let it be handled normally.

Categories