Background Task Not Waiting For Bot To Be Ready - python

So the goal of this background task is to wait until the bot is ready and then perform the function monitorGame() unfortunately this is not the case when I run the bot.
Code With Problem:
import json
import requests
import discord
from gamestop import monitorGame
from datetime import datetime
from time import sleep
from discord.ext import tasks, commands
from discord.ext.commands import errors
from discord.utils import get
from discord_webhook import DiscordWebhook, DiscordEmbed
from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from bs4 import BeautifulSoup
# Prefix
bot = commands.Bot(command_prefix='/')
bot.remove_command("help")
# Bot Event
#bot.event
async def on_ready():
print("[+] Bot Is Alive [+]")
await bot.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name=f"Game"))
# Start Monitor
#tasks.loop(seconds=1)
async def monitor():
# Wait Until Bot Is Ready
await bot.wait_until_ready()
# Run Function
monitorGame()
# Start Task
monitor.start()
# Run bot
bot.run(token)
Since the function monitorGame() uses selenium, what tells me that the function is running before the bot is ready is that a browser opens before the bot prints Bot Is Alive.
What ends up happening is the function runs before the bot is ready and just screws everything up.
Some side notes:
The function includes selenium and opens a browser.
I am using repl to run this bot.
The function monitorGame() essentially opens a browser and parses the html that's about it.

You could simply check how long it takes to start up the selenium part, then mesure the time and insert a time.sleep('seconds') until it is started up, probably the easiest fix in this case

Related

Async function blocking discord.py heartbeat

I am writing a discord bot which triggers a web scraping function every 5 minutes. Even though I am running the function by calling client.loop.create_task, it still results in the following error every time:
Shard ID None heartbeat blocked for more than 10 seconds.
What can be changed to fix this error? I thought I had changed my code to call the function in a non-blocking way but it seems it still blocks.
import discord
import os
from dotenv import load_dotenv
from scrape import *
from apscheduler.schedulers.asyncio import AsyncIOScheduler
from apscheduler.triggers.cron import CronTrigger
load_dotenv()
intents = discord.Intents.default()
intents.messages = True
intents.message_content = True
# instantiate discord client
client = discord.Client(intents=intents)
async def trigger_scrape():
client.loop.create_task(scrape(client))
# discord event to check when the bot is online
#client.event
async def on_ready():
scheduler = AsyncIOScheduler(standalone=True)
scheduler.add_job(trigger_scrape, CronTrigger(minute="*/5")) # run every 5 minutes
scheduler.start()
client.run(os.getenv('TOKEN'))

Run other commands alongside selenium

I am currently trying to make a discord bot that starts a selenium thread. It works but the only issue is that I cannot use other commands if selenium takes too long. It will eventually respond to the next command but it's only responds after selenium is finished.
This is what I have:
import threading
import discord
import time
from selenium import webdriver
from discord.ext import tasks, commands
client = commands.Bot(command_prefix='!')
def start(url):
driver = webdriver.Firefox()
driver.get(url)
time.sleep(10)
driver.close()
#client.command()
async def rq(ctx):
#if link == None:
#await ctx.send("Please send a link!")
await ctx.send("Started!")
threading(target=start("https://google.com/")).start()
#client.command()
async def sc(ctx):
await ctx.send("some command")
if __name__ == "__main__":
client.run(token)
Any solutions would be helpful!
The way you invoke the thread is incorrect:
threading(target=start("https://google.com/")).start()
What this does is:
Call the start function on the main thread, passing it the URL.
Wait for the function to finish.
Take the returned value (None) and pass it as the target function to the thread constructor (I think you meant threading.Thread there by the way).
So by the time the thread starts, the actual work has already completed on the main thread, and the thread itself does nothing.
The correct way to start a thread and pass it some arguments would be:
threading.Thread(target=start, args=("https://google.com/",)).start()
Notice how start is not being followed by (), so we're not calling the function directly; we're passing the function itself to the Thread constructor. The arguments are given as a tuple to the args argument (hence the trailing comma).

Keep bot alive even a function is looping

Im developing a discord covid tracker bot and the information is scraped from a facebook page. I successfully scrape the info and store it to a list, however when I run the bot the bot will work at first but for every 5 minute the bot will be disconnect and not responding because def scrape will be refresh every 5min. So my question is how can I keep the bot to work even the scrape function is looping?
My code:
import discord
import random
import time
import asyncio
from facebook_scraper import get_posts
from discord.ext import commands, tasks
listposts = []
token = 'xxxx'
client = discord.Client()
listposts = []
#tasks.loop(minutes=5)
async def scrape():
wanted = "Pecahan setiap negeri (Kumulatif)" # wanted post
for post in get_posts("myhealthkkm", pages=5):
if post.get("text") is not None and wanted in post.get("text"):
# print("Found", t)
listposts.append(post.get("text"))
else:
pass
# print("Not found")
print(listposts)
#client.event
async def on_message(message):
if message.content.startswith("-malaysiacase"):
await message.channel.send(listposts)
#client.event
async def on_ready():
print("RUN")
scrape.start()
client.run(token)
Result:
After 5 minutes (the scrape function reload), the bot couldn't respond to user request anymore until the scraping process completed
facebook_scraper module is not asynchronous therefore blocking, which will make your bot freeze till it has completed and miss heartbeats which causes disconnect.
Do not use time module inside a discord bot either you have to use asyncio.sleep for the same reason.
Some alternatives you can do are: use BS4 in conjunction with AIOHTTP.
Or look at running your sync function in loop.run_in_executor.
There are some examples here: Python lib beautiful soup using aiohttp

How do I use schedule py and Discord py together?

Main goal:
Send a message to a channel every Wednesday at 08:00
This is my current code:
import schedule
import time
import discord
import asyncio
from discord.ext import commands, tasks
from discord.ext.tasks import loop
client = discord.Client()
# IMPORTANT
channel =
botToken = ""
async def sendloop():
while True:
schedule.run_pending()
await asyncio.sleep(1)
#client.event
async def on_ready():
general_channel = client.get_channel(channel)
print('ready')
schedule.every(2).seconds.do(lambda:loop.create_task(general_channel.send('TEST')))
client.run(botToken)
So far, there are no errors, just stuck on "ready". I am a beginner using VS Code.
I wouldn't recommend using scheduler, since discord the extension task which can do the same as what you are trying to implement in your code:
from discord.ext import commands, tasks
ch = id_channel
client = commands.Bot(command_prefix='.')
TOKEN = "Token"
#every week at this time, you can change this to seconds=2
#to replicate what you have been testing
#tasks.loop(hours=168)
async def every_wednesday():
message_channel = client.get_channel(ch)
await message_channel.send("Your message")
#every_wednesday.before_loop
async def before():
await client.wait_until_ready()
every_wednesday.start()
client.run(TOKEN)
If you were to run this code on the time you want it to be repeated, it will accomplish what you want. Another approach is checking on the before() function to check if it is the right time to run if you don't want to wait and run the code on the day you want this to run.
But if you really want to use the schedule module, this post my help you: Discord.py Time Schedule

Discord Bot Python send a message every hour

I have a problem with discord's bot.
I have done a script which calculate the weather every hour and I want to send the result to discord with bot:
import Secret
import discord
result = "temp is ...."
TOKEN = Secret.BOT_TOKEN
client = discord.Client()
client.send(result)
client.run(TOKEN)
I have searched on google but I have not found an answer to send the result automatically.
Can you help me?
If you're using python just put it in a while loop and have it send the message and sleep for an hour.
for sleep you can import time
Something like:
while true:
client.send(result)
sleep(3600)
Important:
Your bot will be 100% inactive while you sleep it, so if you use it for more than just weather this might not be the solution you're looking for.
Using the time module prevents your bot from doing anything else during the time that it is sleeping.
Use tasks. Just put what you want executed in the task() function:
from discord.ext import tasks
#tasks.loop(seconds=60) # repeat once every 60 seconds
async def task():
pass
mytask.start()

Categories

Resources