How to send message with eventsub

i have with code

from twitchAPI.twitch import Twitch
from twitchAPI.chat import Chat
from twitchAPI.helper import first
from twitchAPI.eventsub.webhook import EventSubWebhook
from twitchAPI.object.eventsub import ChannelFollowEvent, ChannelChatMessageEvent
from twitchAPI.oauth import UserAuthenticator
from twitchAPI.type import AuthScope
from loguru import logger
import asyncio


EVENTSUB_URL = '#'
APP_ID = '#'
APP_SECRET = '#'
TARGET_SCOPES = [AuthScope.CHANNEL_BOT, AuthScope.USER_WRITE_CHAT]
mod_id = "#"
br_id = "#"


async def on_follow(data: ChannelFollowEvent):
    print(f'{data.event.user_name} now follows {data.event.broadcaster_user_name}!')


async def on_message(data: ChannelChatMessageEvent):
    print("get message")


async def eventsub_webhook_example():
    logger.info("start twitch")
    try:
        twitch = await Twitch(APP_ID, APP_SECRET)
        logger.info("success twitch")
    except Exception as e:
        logger.error(e)

    logger.info("start auth")
    try:
        token = "#"
        refresh_token = "#"
        await twitch.set_user_authentication(token, TARGET_SCOPES, refresh_token)
        logger.info("end auth")
    except Exception as e:
        logger.error(e)

    eventsub = EventSubWebhook(EVENTSUB_URL, 80, twitch)
    await eventsub.unsubscribe_all()
    eventsub.start()
    await eventsub.listen_channel_follow_v2(br_id, mod_id, on_follow)
    await eventsub.listen_channel_chat_message(br_id, mod_id, on_message)
    await twitch.send_chat_message(br_id, mod_id, "bot start")


    try:
        input('press Enter to shut down...')
    finally:
        await eventsub.stop()
        await twitch.close()
    print('done')


asyncio.run(eventsub_webhook_example())

in chatters list bot has badge “chat bot“
but when i send with “await twitch.send_chat_message(br_id, mod_id, “bot start”)“ i get message without badge

what i can do?

EventSub is unrelated to sending chat messages it’s just for listening.

To send a chat message you need to use the Send Chat Message endpoint, with an App access token (so this can only be done server-side, with a confidential app). You also need to have the chatting user granting the user:bot scope to your app, and either that user be a moderator in the channel you’re sending messages to or the channel granting your app the channel:bot scope.

Because you’re not getting the badge when you’re sending messages, you’re likely using a User Token, rather than App token.

how to get app access token with the needed scopes?
i do with

from twitchAPI.twitch import Twitch
from twitchAPI.chat import Chat
from twitchAPI.helper import first
from twitchAPI.eventsub.webhook import EventSubWebhook
from twitchAPI.object.eventsub import ChannelFollowEvent, ChannelChatMessageEvent
from twitchAPI.oauth import UserAuthenticator
from twitchAPI.type import AuthScope
from loguru import logger
import asyncio
import requests
import json


def to_serializable(obj):
    if obj is None:
        return None
    if isinstance(obj, (str, int, float, bool)):
        return obj
    if hasattr(obj, '__dict__'):
        return {k: to_serializable(v) for k, v in obj.__dict__.items()}
    if hasattr(obj, 'dict'):
        return to_serializable(obj.dict())
    return str(obj)


url = 'https://api.twitch.tv/helix/chat/messages'

app_token = None

headers = {
    'Authorization': f'Bearer {app_token}',
    'Client-Id': '#',
    'Content-Type': 'application/json'
}

EVENTSUB_URL = '#'
APP_ID = '#'
APP_SECRET = '#'
TARGET_SCOPES = [AuthScope.CHANNEL_BOT, AuthScope.USER_WRITE_CHAT, AuthScope.USER_BOT]
scopes = [AuthScope.USER_WRITE_CHAT, AuthScope.USER_BOT]
mod_id = "#"
br_id = "#"


async def on_follow(data: ChannelFollowEvent):
    print(f'{data.event.user_name} now follows {data.event.broadcaster_user_name}!')


async def on_message(data: ChannelChatMessageEvent):
    send_data = {
        "broadcaster_id": "#",
        "sender_id": "#",
        "message": f"Echo: {data.event.message.text}",
        "for_source_only": True
    }

    response = requests.post(url, headers=headers, json=send_data)
    print(response.status_code)
    print(response.json())
    print("get message")


async def eventsub_webhook_example():
    logger.info("start twitch")
    twitch = await Twitch(APP_ID, APP_SECRET)
    logger.info("success twitch")

    logger.info("start auth")
    token = "#"
    refresh_token = "#"
    await twitch.set_user_authentication(token, TARGET_SCOPES, refresh_token)
    logger.info("end auth")

    global headers
    app_token = twitch.get_app_token()
    await twitch.set_app_authentication(app_token, scopes)
    headers['Authorization'] = f'Bearer {app_token}'
    logger.info(f"app token is getting")

    eventsub = EventSubWebhook(EVENTSUB_URL, 80, twitch)
    await eventsub.unsubscribe_all()
    eventsub.start()
    await eventsub.listen_channel_follow_v2(br_id, mod_id, on_follow)
    await eventsub.listen_channel_chat_message(br_id, mod_id, on_message)

    try:
        logger.success("BOT STARTED. Ctrl+C for stop...")
    except KeyboardInterrupt:
        logger.info("\nStop...")
    finally:
        await eventsub.stop()
        await asyncio.sleep(1)
        await twitch.close()
    print('done')


if __name__ == "__main__":
    asyncio.run(eventsub_webhook_example())

but with when I try to send a message
{‘error’: ‘Unauthorized’, ‘status’: 401, ‘message’: ‘The sender must have authorized the app with the user:write:chat and user:bot scopes.’}

App Access tokens don’t have scopes

The steps are:

  • First you get an oAuth token from the broadcaster with channel:bot
  • Then you get an oAuth token from the account that is the bot with user:bot and the relevant chat scopes: user:write:chat
  • Store both user tokens if needed.

THEN you generate an app access token and use that with Send Chat. (note the scopes listed as minimal and you may need more for other operations) (My Reference Documenation this is for eventsub but the logic applies on how authentication operations, just for send chat needs different/extra scope(s))

Conceptually you already did some of these steps to get eventsub working (with the chat bot tag in the user list) as that requires channel:bot/user:bot from the various users.

The Send Chat API uses “prior user authentication” to allow access to send (in the same way as doing prior auth allows eventsub conduits or webhooks to allow type/topic access as that uses an app access token also)

it worked thanks!

new question:
app token have “expires_in“
how to refresh it or i need to create a new one every time?

and as I understand it, I can’t combine Eventsub and IRC. Right?

For app tokens, you just generate a new one when current one expires.

As for combining EventSub and IRC, there’s nothing stopping you connecting to and using both services, how you ‘combine’ them will be entirely up to you within your app.

I tried listening to two channels and everything worked.

    await eventsub.listen_channel_chat_message(br_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(shem_id, mod_id, on_message)

Question: Can I use this setup to listen to all the channels I want, or is there a limit to the number of channels I can listen to?

You can find the limits regarding EventSub over websockets here: https://dev.twitch.tv/docs/eventsub/handling-websocket-events/#subscription-limits, or if using Conduits: https://dev.twitch.tv/docs/eventsub/handling-conduit-events/#limits

If you have authentication from the user, then you have permission to be present wrt to chat join rate limits

I saw these words in docs:

After these words, I thought that only 5 channels were possible.

but I tried to connect to 6 channels and everything worked:

    await eventsub.listen_channel_chat_message(br_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(shem_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(kotaro_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(kwank_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(hatiko_id, mod_id, on_message)
    await eventsub.listen_channel_chat_message(gordey_id, mod_id, on_message)

Did I misunderstand something?

Shard != Channel/subscription

A conduit has shards (websockets or webhooks), msot bots use one or two shards.

A conduit has subscriptions (as does a webhook or a websocket) (chat channels you want to listen to involves creating a subscription)

This topic was automatically closed 30 days after the last reply. New replies are no longer allowed.