0

I'm trying to create a python program that continuously processes the latest message sent in a specific channel (and prints the message as a string). I've looked on stackoverflow for a solution, but I can't seem to find it. May you guys review my code for me?


import discord
import asyncio
import nest_asyncio
nest_asyncio.apply()

class MyClient(discord.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def turn_on(self):
        print('my account:')
        print(self.user.name)
        print(self.user.id)
        print('------')

        # create a message_to_string task and run it in the background
        self.bg_task = self.loop.create_task(self.messages_to_string())

    async def messages_to_string(self):
        runs_today = 0
        channel = self.get_channel(1234567890000000) # put the channel's id here
        msg = await channel.history(limit=1).flatten()
        msg = msg[0]
        while not self.is_closed():
            runs_today += 1
            await channel.send(runs_today)
            await asyncio.sleep(60) # task runs every minute
        print(msg)

client = MyClient()

client.run('my_token') #put my personal token in here

I'm always getting this error: RuntimeError: Cannot close a running event loop

do you have any suggestions on how to fix it?

Thank you!

EDIT:

oops, I forgot to post the trace. Here it is (I hid my token because it has sensitive information)

     31 client = MyClient()
---> 32 client.run('my_token') #put my personal token in here

~\Anaconda3\lib\site-packages\discord\client.py in run(self, *args, **kwargs)
    712             future.remove_done_callback(stop_loop_on_completion)
    713             log.info('Cleaning up tasks.')
--> 714             _cleanup_loop(loop)
    715 
    716         if not future.cancelled():

~\Anaconda3\lib\site-packages\discord\client.py in _cleanup_loop(loop)
     93     finally:
     94         log.info('Closing the event loop.')
---> 95         loop.close()
     96 
     97 class _ClientEventTask(asyncio.Task):

~\Anaconda3\lib\asyncio\selector_events.py in close(self)
     92     def close(self):
     93         if self.is_running():
---> 94             raise RuntimeError("Cannot close a running event loop")
     95         if self.is_closed():
     96             return

RuntimeError: Cannot close a running event loop
DarthQuack
  • 1,254
  • 3
  • 12
  • 22
  • can you post the full trace back? – Łukasz Kwieciński Feb 06 '21 at 00:15
  • @ŁukaszKwieciński posted! Thanks for the reply – Teodor Sauca Feb 06 '21 at 00:42
  • Are you using a weird IDE? This seems related: https://stackoverflow.com/questions/57639751/how-to-fix-runtime-error-cannot-close-a-running-event-loop-python-discord-bot – effprime Feb 06 '21 at 04:16
  • @effprime hi, I tried it in spyder and got the exact same error. I also applied nest_asyncio so I'm still confused as to where my error is. Thanks for the reply! – Teodor Sauca Feb 06 '21 at 18:45
  • Sorry, I am referring to the comment that says `I encountered the same problem trying to run Discord examples on Jupyter Notebook. Moving to plain python script solved it for me.` Admittedly this is a workaround, but probably not a bad one – effprime Feb 06 '21 at 21:42

1 Answers1

0

I suggest using the Tasks extenstion:

import discord
from discord.ext import tasks


class MyClient(discord.Client):
    def __init__(self, *args, **kwargs):
        super().__init__(*args, **kwargs)

    async def turn_on(self):
        print('my account:')
        print(self.user.name)
        print(self.user.id)
        print('------')

        
        self.runs_today = 0
        # Start the task
        self.messages_to_string.start()

    @tasks.loop(seconds=60.0)
    async def messages_to_string(self):
        channel = self.get_channel(1234567890000000) # put the channel's id here
        msg = await channel.history(limit=1).flatten()
        msg = msg[0]
        self.runs_today += 1
        await channel.send(self.runs_today)
        print(msg)

client = MyClient()
client.run('my_token')

This runs your function every 60 seconds.

jacksoor
  • 353
  • 1
  • 12