I want to create a Python Bot which tracks the time a user has spent in voice state on a server to create a ranking system. Unfortunaley i dont know how to update the guild.members list and thus the member.voice value.
I tried doing a while loop but the list didnt seem to update.
Help would be greately appreciated.
# bot.py
import os
import asyncio
import discord
import random
import datetime
from discord.utils import get
import time
from dotenv import load_dotenv
from discord.ext import tasks
load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
GUILD = os.getenv('DISCORD_GUILD')
client = discord.Client()
#client.event
async def on_ready():
print("Bot is ready")
while True:
time.sleep(2)
guild = discord.utils.find(lambda g: g.name == GUILD, client.guilds)
for m in guild.members:
print(m.voice)
time.sleep(2)
client.run(TOKEN)
You can use the on_voice_state_update() event to keep track of every single member that connects / disconnect from a voice channel. Make sure to use the discord.ext.commands client object.
import discord
from discord.ext import commands
client = commands.Bot(command_prefix='$')
#client.event
async def on_voice_state_update(member, before, after):
if not before.channel and after.channel:
await start_tracking(member) #your method that tracks the time
#Remember that it has to be a coroutine
if before.channel and not after.channel:
await stop_tracking(member)
edit: please do not use time.sleep() in async scripts. use asyncio for stuff like sleeping and for loops
Related
The plan for this bot is to wake up --> retrieve data I need --> terminate itself.
I've tried using client.logout() and client.close(), but the program won't stop after it runs. Any advice?
import discord
import os
from discord.ext import tasks
from discord.ext import commands
discord_client = discord.Client()
#discord_client.event
async def on_ready():
for guild in discord_client.guilds:
if guild.name == GUILD:
break
print(
f'{discord_client.user} is connected to the following guild:\n'
f'{guild.name}(id: {guild.id})'
)
# Send message when Bot wakes up
channel = discord_client.get_channel(ID)
await channel.send("*wakes up and starts working*")
retrieve_data.start()
await discord_client.logout()
#tasks.loop(count=1)
async def retrieve_data():
# do things here
discord_client.run(TOKEN)
You don't have your token defined, import load_dotenv and call it, you have undefined variables, also logout() is deprecated so use close() instead and it works.
import discord
import os
from discord.ext import tasks
from dotenv import load_dotenv
from discord.ext import commands
load_dotenv()
discord_client = discord.Client()
#discord_client.event
async def on_ready():
# for guild in discord_client.guilds:
# if guild.name == GUILD:
# break
# print(
# f'{discord_client.user} is connected to the following guild:\n'
# f'{guild.name}(id: {guild.id})'
# )
# Send message when Bot wakes up
# channel = discord_client.get_channel(ID)
# await channel.send("*wakes up and starts working*")
await retrieve_data.start()
await discord_client.close()
#tasks.loop(count=1)
async def retrieve_data():
print("test")
discord_client.run(os.getenv("TOKEN"))
Im using the discord.py library and using replit for the bot, but my code doesnt work.
my code:
import os
import discord
from discord.utils import get
client = discord.Client()
#client.event
async def on_ready():
print ("We have logged in as {0.user}".format(client))
#client.event
async def on_message(message):
if message.content == ";":
member = message.author
role = get(member.guild.roles, name="Recruiter")
await member.add_roles(role)
client.run(os.getenv("TOKEN"))
First of all, you're using client object and it is not a bot.
This is the way to create a proper bot (not client):
from discord.ext import commands
bot = commands.Bot(command_prefix="!")
You can't code reactions roles without reading the discord.py docs. It involves lots of stuff.
If you want to code it yourself, the only way is to learn and do.
I added an option to my bot to change the role color after some time. But, after a while, this option stops working. How can I make this option work all the time?
from asyncio.tasks import create_task
import discord
from discord import client
from discord.ext import commands
import asyncio
from discord.utils import get
import os
from keep_alive import keep_alive
bot = commands.Bot(command_prefix = ".")
#bot.event
async def on_ready():
print("Bot jest gotowy!")
#bot.command()
async def r1(ctx):
while True:
role = discord.utils.get(ctx.guild.roles, id=869949352246902846)
await role.edit(color=0xff0000, reason="red")
await asyncio.sleep(0.25)
await role.edit(color=0xcc7306, reason="orange")
await asyncio.sleep(0.25)
await role.edit(color=0xfbff03, reason="yellow")
await asyncio.sleep(0.25)
await role.edit(color=0x2fff00, reason="green")
await asyncio.sleep(0.25)
await role.edit(color=0x0073ff, reason="blue")
await asyncio.sleep(0.25)
await role.edit(color=0xae00ff, reason="purple")
await asyncio.sleep(0.25)
It stops working because you're being ratelimited by Discord for spamming their API. Don't do this.
This is due to the fact that discord is rate-limiting you because you're spamming their API, this could get you banned but if you really want it to change the colours I recommend making the time in-between a lot higher such as 40-60 seconds. Overall this is a very risky thing to do.
I still have not figured out how to add/remove roles on the bot itself, without executing commands in the chat. It has to be silently in the background. Can someone please help me.
Current code below that does work but not the way I want it to. I do not want the bot to type a command to give itself a role, I need it to automatically give it silently without any chat messages being executed. My ideal idea is to execute the addRole function in the on_ready event somehow, without sending message to get a role.
import aiohttp
from datetime import datetime
from dotenv import load_dotenv
from discord.ext import commands
import discord
import os
load_dotenv()
DISCORD_TOKEN = os.getenv("DISCORD_TOKEN")
bot = commands.Bot(command_prefix="$")
bot.remove_command('help')
#bot.event
async def on_ready():
await bot.wait_until_ready()
bot.session = aiohttp.ClientSession()
await bot.get_channel(402353715718277809).send("$addRole")
#bot.command()
async def addRole(ctx):
role = discord.utils.get(ctx.guild.roles, name="market_green")
member = ctx.guild.get_member(bot.user.id)
await member.add_roles(role)
bot.run(DISCORD_TOKEN)
The guild object in discord.py has a .me attribute (docs) which represents yourself in that guild.
So on start you can get that guild based on it's id (in the on_ready event) and assign yourself a role with add_roles, example code(with guildid the id of the guild you want the role in):
guild = bot.get_guild(guildid)
role = discord.utils.get(guild.roles, name="market_green")
await guild.me.add_roles(role)
We are creating an Discord bot.
The Problem is that no error is in Console but the Chat in Discord is also empty. So no response at all. Could you please help me and say what my error is and how to resolve the problem
Best Wishes,
Niktix
import discord
from discord.ext import commands
import asyncio
from dotenv import load_dotenv
from discord.ext.commands import Bot
import askai
import numpy
import random
import json
import datetime as DT
from time import sleep
import sLOUT as lout
import os
botStartTime = DT.datetime.now()
ver = ['v1.0.8', '2021-01-13']
config = 'config.yml'
bot = commands.Bot(command_prefix = '!')
lout.writeFile('AskAIBotLogs.txt', '\naskai initialisiert!', True)
load_dotenv()
#bot.command(pass_context=True)
async def time(ctx):
startTime = DT.datetime.now()
await ctx.send('Auf dem server ist aktuell folgende Uhrzeit: {}'.format(DT.datetime.now()))
lout.log(config, startTime, 'time')
#bot.event
async def on_ready():
await bot.change_presence(activity=discord.Activity(type=1, name='Beantwortet Fragen', url='https://www.youtube.com/watch?v=e3tuUKGIaGw', platform='YouTube', assets='askai',))
lout.log(config, botStartTime, None, None, True)
print('Eingeloggt als {}'.format(bot.user.name))
#bot.event
async def on_message(message):
if message.author.bot:
return
if message.channel.name != "askai-support":
return
if message.content.startswith("!"):
return
await bot.process_commands(message)
await message.channel.send(askai.ask(message.content))
bot.run('token')
Why does it not work? Well, the answer is fairly simple. Please refer to the following lines you provided:
#bot.event
async def on_message(message):
if message.author.bot:
return
if message.channel.name != "askai-support":
return
At this point in the code, you provide the channel name. Although, you don't provide the channel ID afterward. Therefore the bot cannot get said channel. In order to get the channel ID, please refer to Discord's official guide here. Upon doing that, make the same line of code as above, although replace "message.channel.name" with "message.channel.ID". Let me know if you have any further questions. Best Regards,