shizmob / pydle

An IRCv3-compliant Python 3 IRC library.
BSD 3-Clause "New" or "Revised" License
154 stars 47 forks source link

I want to post an RSS feed without user interaction, which callback should I use? #178

Closed Mosesofmason closed 2 years ago

Mosesofmason commented 2 years ago

I can see all the callbacks are based on events, but I want to post on time-based, I could not find which callback to use. Could anyone shed light on this?

theunkn0wn1 commented 2 years ago

Pydle's callbacks are event indeed event driven, as that is how IO tends to be handled.

There isn't anything in the IRC specifications that MUST generate an event periodically, however several IRC servers will send a PING periodically as a keep-alive.

Pydle handles this using the Client.on_raw_ping, but doesn't expose a public callback you can override as of current.

If you want a stronger garuntee, I suggest making your own periodic task.

To create a callback that fires periodically, you could create something using asyncio.create_task and asyncio.sleep.

Here is an example:

import asyncio

import pydle

from typing import Optional

# Simple echo bot.
class MyOwnBot(pydle.Client):
    def __init__(self, *args, **kwargs):
        super(MyOwnBot, self).__init__(*args, **kwargs)
        # cannot start the task here, as the event loop might not be running yet.
        self._periodic_task: Optional[asyncio.Task] = None

    async def periodic_task(self):
        while True:
            await self.tick()
            await asyncio.sleep(5)

    async def tick(self):
        return await self.message(target="#bottest", message="tock!")

    async def on_connect(self):
        await self.join('#bottest')
        # but we can start it here, since the loop must be running by this point.
        self._periodic_task = asyncio.create_task(self.periodic_task())

    async def on_message(self, target, source, message):
        # don't respond to our own messages, as this leads to a positive feedback loop
        if source != self.nickname:
            await self.message(target, message)

client = MyOwnBot('MyBot', realname='My Bot')
client.run('localhost', tls=True, tls_verify=False)
Mosesofmason commented 2 years ago

Thanks, it works! ❤