Discord Bot Task Creation Problem
I’m building a Discord bot and need help with running background tasks. I want to create a function that tracks server activity and writes the data to a file every few seconds.
The issue happens when I try to start the background task. I get an AttributeError saying the loop attribute can’t be accessed in non-async contexts.
import os
import time
import asyncio
import discord
from discord.ext import commands, tasks
BOT_TOKEN = 'bot_token_here'
SERVER_NAME = "my_server"
msg_count = member_joins = 0
intents = discord.Intents.default()
intents.message_content = True
bot = discord.Client(intents=intents)
async def track_activity():
await bot.wait_until_ready()
global msg_count, member_joins
while not bot.is_closed():
try:
with open("activity_log.txt", "a") as file:
file.write(f"Timestamp: {int(time.time())}, Messages: {msg_count}, New Members: {member_joins}\n")
msg_count = 0
member_joins = 0
await asyncio.sleep(10)
except Exception as error:
print(error)
await asyncio.sleep(10)
@tasks.loop(seconds=10)
async def send_welcome(text_channel: discord.TextChannel):
await text_channel.send("Hello everyone!")
@bot.event
async def on_ready():
if not send_welcome.is_running():
welcome_channel = await bot.fetch_channel("channel_id_here")
send_welcome.start(welcome_channel)
for server in bot.guilds:
if server.name == SERVER_NAME:
break
print(f'{bot.user} connected to: {server.name} (ID: {server.id})')
await bot.change_presence(
activity=discord.Activity(name='monitoring', type=discord.ActivityType.watching)
)
@bot.event
async def on_member_join(new_member):
global member_joins
member_joins += 1
for ch in new_member.guild.channels:
if str(ch) in ['general', 'welcome']:
await ch.send(f"Welcome {new_member.mention}!")
@bot.event
async def on_message(msg):
global msg_count
msg_count += 1
server_obj = bot.get_guild(12345678)
allowed_channels = ["general", "commands", "chat"]
authorized_users = ["admin_username"]
if str(msg.channel) in allowed_channels and str(msg.author) in authorized_users:
if msg.content == "!greet":
await msg.channel.send("Hello there!")
elif msg.content == "!count":
await msg.channel.send(f"Total members: {server_obj.member_count}")
bot.loop.create_task(track_activity())
bot.run(BOT_TOKEN)
Error message:
AttributeError: 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_hook
What’s the proper way to start background tasks in Discord.py? Should I use setup_hook instead?