import os
import discord
import requests
import time
import datetime
class MyClient(discord.Client):
async def on_ready(self):
await client.change_presence(activity=discord.Activity(type=0, name='HIDDENSTATUS'))
print('Logged on as {0}!'.format(self.user))
async def on_message(self, message):
msglower = message.content.lower()
channelStatusSV = client.get_channel(HIDDENCHANNELID)
if msglower == '!refresh':
standard = formated_info('HIDDENIP', '36963', 'ok')
messageStandard = await channelStatusSV.fetch_message(HIDDENMESSAGEID)
await messageStandard.edit(content=standard)
client = MyClient()
client.run('HIDDENTOKEN')
This is the full script (with some hidden info like IP, URL, etc).
It fetches my game server info into an embedded bot message. Currently, it fetches info on demand.
How can I change it to automatically fetch every minute?
Assuming that you're using discord.py; you can use tasks! Have it loop on the interval you want, query the server, and update the message.
Related
I understand that usually the discord bots are in a listening (blocking) loop, but how can I create a function that connects, send a message or perform any action and disconnect in a non blocking flow?
I'm using discord.py and I'm looking for something like:
import discord
TOKEN = "mYtOkEn"
discord.connect(TOKEN)
discord.send("I'm sending this message")
discord.disconnect()
I already tryied playing with the async but have problems with the threading, so was wondering if there is something more simple.
It is for a button that when clicked, perform that action but after that it can continue working on other tasks
Thanks beforehand
One way you could accomplish this is by using a custom event loop.
Example:
import discord
import asyncio
from threading import Thread
TOKEN = "secret"
client = discord.Client()
def init():
loop = asyncio.get_event_loop()
loop.create_task(client.start(TOKEN))
Thread(target=loop.run_forever).start()
#client.event
async def on_message(message):
if message.author == client.user:
return
await message.channel.send('Hello!')
#client.event
async def on_ready():
print("Discord bot logged in as: %s, %s" % (client.user.name, client.user.id))
init()
print("Non-blocking")
Take a look at this for more info: C-Python asyncio: running discord.py in a thread
Thank you for your help and support. With the SleepyStew answer I could find the path to solve it and went this way:
import discord
import asyncio
def discord_single_task():
# Define Coroutine
async def coroutine_to_run():
TOKEN = "Secret"
# Instantiate the Client Class
client = discord.Client()
# # Start (We won't use connect because we don't want to open a websocket, it will start a blocking loop and it is what we are avoiding)
await client.login(TOKEN)
# Do what you have to do
print("We are doing what we want to do")
# Close
await client.close()
# Create Loop to run coroutine
loop = asyncio.new_event_loop()
llll = loop.create_task(coroutine_to_run())
loop.run_until_complete(llll)
return 'Action performed successfully without a blocking loop!'
I am not able to change the status. I want to develop my own bot and have to add more features too
# Importing Modules
import discord
import asyncio
import random
import DateTime
from discord.ext import commands
from urllib import parse, request
import re
import time
# Importants
bot = commands.Bot(command_prefix='*', description="This is a Helper Bot")
client = discord.Client()
# ***ADDING FEATURES***
# Getting Online And Changing status
async def my_background_task():
await client.wait_until_ready()
# Setting `Playing ` status
await bot.change_presence(activity=discord.Game(name="With Your Life"))
time.sleep(5)
# Setting `Streaming ` status
await bot.change_presence(activity=discord.Streaming(name="Kartik Jain", url="https://youtube.com/c/KartikJainChannel"))
time.sleep(5)
# Setting `Listening ` status
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.listening, name="To *help"))
time.sleep(5)
# Setting `Watching ` status
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=" Your Nonsense"))
time.sleep(5)
# While Loop To loop changing statuses
while not bot.is_closed():
bot.bg_task = bot.loop.create_task(my_background_task())
# Making the bot online
client.run('My_ID')
You have to change the bot with client and you have to change this my_background_task() to this: on_ready().
Just look at this code:
import discord
import asyncio
import random
import DateTime
from discord.ext import commands
from urllib import parse, request
import re
import time
# Importants
bot = commands.Bot(command_prefix='*', description="This is a Helper Bot")
client = discord.Client()
# ***ADDING FEATURES***
# Getting Online And Changing status
#client.event
async def on_ready():
await client.change_presence(activity=discord.Streaming(name="My live",url="http://www.twitch.tv/G4merStop"))
time.sleep(5)
await client.change_presence(activity=discord.Streaming(name="Your live",url="http://www.twitch.tv/G4merStop"))
time.sleep(5)
# ^^^^ here you can see what you can do in the docs ^^^^
# Making the bot online
client.run('My_ID')```
First of all, you're actually creating 2 different instances of the client, client using discord.Client and bot using commands.Bot. You're using bot to change the presence, and in the end, you're running the client instance, which makes part done using bot totally useless.
You don't need to use discord.Client, because commands.Bot has all the methods and attributes of discord.Client.
Next, you should change time.sleep() to await asyncio.sleep() because it's blocking your code and also put the bot.loop.create_task() method inside on_ready event
I have been trying to create a bot for Discord using the discord.py library however when I am running the program it is not sending the message as expected. It is a simple bot that is suppose to send a message every 10 minutes to a channel. I am not getting any error messages in the command line and can't seem to see any obvious errors? Any help would be greatly appreciated.
import asyncio
client = discord.Client()
async def my_background_task():
await client.wait_until_ready()
counter = 0
channel = discord.Object(id='my channel ID goes here')
while not client.is_closed:
counter += 1
await message.channel.send("TEST")
await asyncio.sleep(5) # task runs every 60 seconds
#client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
client.loop.create_task(my_background_task())
client.run('My token goes here')
Although creating a task could work, I wouldn't recommend it when there are better options. Dpy's command.ext addon has a task based system built in directly, so let's look into using that instead.
import discord
from discord.ext import tasks
client = discord.Client()
#tasks.loop(minutes=10)
async def my_background_task():
"""A background task that gets invoked every 10 minutes."""
channel = client.get_channel(754904403710050375) # Get the channel, the id has to be an int
await channel.send('TEST!')
#my_background_task.before_loop
async def my_background_task_before_loop():
await client.wait_until_ready()
my_background_task.start()
client.run('Your token goes here')
The time until which the above loop will run is dependent upon human psychology, laws of energy and cosmos.
That is:
• You get bored of it
• The power goes down and your script stops working
• The universe explodes
Read more about it here:
https://discordpy.readthedocs.io/en/latest/ext/tasks/
If the channel ID is a string, It should be an integer.
Turn this:
channel = discord.Object(id='my channel ID goes here')
into:
channel = discord.Object(id=101029321892839) # an example ID
If that doesn't solve your problem, try setting 'message.channel.send' to 'channel.send' and client.is_closed should be
client.is_closed() # put brackets
Instead of client.loop.create_task(my_background_task()), just put the background function in the on_ready event. And take out await client.wait_until_ready() and just put the function in the on_ready event as well.
I have also changed the client variable, taken out unnecessary code, and added some modules.
import asyncio, discord
from discord.ext import commands
client = commands.Bot(command_prefix = ".") # If you don't want a prefix just take out the parameter.
async def my_background_task():
channel = discord.Object(id='my channel ID goes here')
while True:
await channel.send("TEST")
await asyncio.sleep(5) # task runs every 60 seconds
#client.event
async def on_ready():
print('Logged in as')
print(client.user.name)
print(client.user.id)
print('------')
my_background_task()
client.run('My token goes here')
Also in future when posting a question, please tag the python version as I don't know which version it is and then this and other answers could be wrong.
I have a question for experts here. I am creating background tasks for my Discord bot and I got it working as I wanted but I would like to implement a feature that will allow me to ignore data that was already sent. I am using data that is requested via requests as it changes over time.
Here is part of my code and this works as intended but I can't figure out how to add a part to check sent messages and not repeat it. I set 1 minute for testing to see does it work and this will change later on.
Thanks in advance
import discord
import requests
import asyncio
import json
from datetime import datetime, timezone
import math
from discord.ext import commands, tasks
from discord.ext.commands import Bot
import discord.utils
from itertools import cycle
client = discord.Client()
status = (['Scraping VATSIM Data','Anyone online?','What can I show you?', 'Check our social media for updates!'])
#client.event
async def on_ready():
change_status.start()
auto_online.start()
# await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="VATSIM Data!"))
print('We have logged in as {0.user}'.format(client))
#tasks.loop(minutes=1)
async def auto_online():
# send request to vatsim data
t = requests.get('http://cluster.data.vatsim.net/vatsim-data.json').json()
xy = json.dumps(t)
s = json.loads(xy)
channel1 = client.get_channel(692681048798265347)
# Bookins Data Display
utc = datetime.now(timezone.utc)
# Command for displaying ATC online
online_exists = False
for item in s['clients']:
if item['callsign'] in atc:
online_exists = True
embed = discord.Embed(colour = discord.Colour.purple())
embed.set_author(name='VATAdria Online ATC')
embed.add_field(name='Controller',value=item['realname'],inline=False)
embed.add_field(name='Position', value=item['callsign'], inline=False)
embed.add_field(name='Frequency', value=item['frequency'], inline=False)
await channel1.send( embed=embed)```
After doing some research I found out how to do this via MySQL. So no answers needed for this anymore.
it may hard to me, but i believe on stackoverflow power,
i need to put a number as bot status on my bot.
Here : http://gamers-control-2.000webhostapp.com/count.txt
Also Pic of it : Picture
#time to show status = text that founded in blank website = "41"
#http://gamers-control-2.000webhostapp.com/count.txt
#some how, you say i can type the number, i say the number in web it
change everytime, so i need to get that number to show it as bot status.
import discord
from discord.ext.commands import Bot
from discord.ext import commands
import asyncio
import time
import random
from discord import Game
Client = discord.client
client = commands.Bot(command_prefix = '!')
Clientdiscord = discord.Client()
#client.event
async def on_ready():
await client.change_presence(game=discord.Game(name=http://gamers-control-2.000webhostapp.com/count.txt, type=3))
print('test ready')
client.run("....")
im new with discord.py
You need to first import requests at the beginning
import requests
Then before the ready event
count = requests.get('http://gamers-control-2.000webhostapp.com/count.txt')
And then you set it to
await client.change_presence(game=discord.Game(name=count.text, type=3))
I use await bot.change_presence() like this:
NOTICE:
I am leaving out part of my code
#bot.event
async def on_ready():
replit.clear()
print(f'Logged in as {bot.user.name} - {bot.user.id}')
bot.remove_command('help')
await bot.change_presence(status=discord.Status.online, activity=discord.Game("mod help"))
This is what i use
async def on_ready():
print(f'We have logged in as {bot.user}')
print('Ready!')
return await bot.change_presence(activity=discord.Activity(type=3, name='Add status here'))```