How do you send a message in TwitchIO that's not a response to a command?

Question:

I’m setting up a python TwitchIO chat bot. The getting started example has this:

async def event_message(self, message):
    print(message.content)
    await self.handle_commands(message)

@commands.command(name='test')
async def my_command(self, ctx):
    await ctx.send(f'Hello {ctx.author.name}!')

If the incoming message is a command (e.g. !test), a message is sent back to the channel with ctx.send().

I’d like the option to send a message back to the channel (based on come criteria) whenever any message is received, not just commands. For example:

async def event_message(self, message):
    print(message.content)
    if SOMETHING:
        SEND_MESSAGE_HERE
    await self.handle_commands(message)

I can’t figure out how to do some type of .send to make that happen. This answer: TwitchIO: How to send a chat message? show this:

chan = bot.get_channel("channelname")
loop = asyncio.get_event_loop()
loop.create_task(chan.send("Send this message"))

I tried that and the bot sent a ton of messages instantly and got timed out for an hour.

So, the question is: How do you send a message back to the channel inside event_message

Asked By: Alan W. Smith

||

Answers:

This is the answer I came up with:

bot_account_name = "BOT_ACCOUNT_NAME"


async def event_message(self, message):
    print(message.content)

    if message.author.name.lower() != bot_account_name.lower():
        ws = self._ws
        await ws.send_privmsg('CHANNEL_NAME', 'Message To Send')

    await self.handle_commands(message)

You can do other checks, but it’s important to do the check against the bot account user name. If you don’t the bot will see its own messages and reply to them creating a loop. This is one of the issues I ran into where it send a bunch in no time and got timed out by twitch

Answered By: Alan W. Smith

I found an alternative. I replace the message with a command that I invented for the purpose. The name of the command is "z" but it could have been anything

async def event_message(self, message):
    if message.echo:
        return

    message.content = f"#z {message.content}" # add command name before message

    await self.handle_commands(message)

@commands.command()
async def z(self, ctx: commands.Context):
    print(f"Original message is {ctx.message.content[3:]}n")
Answered By: Kinco

A command passes you a Context (an instance of of Messageable, which defines send()). A Channel is also a Messageable, thus it has a send(). So if your Bot instance is bot:

await bot.connected_channels[0].send('...')

Will send a message to the first channel the bot is connected to.

Answered By: arantius
Categories: questions Tags: , ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.