mrphlip / lrrbot

LoadingReadyRun Twitch chatbot
https://lrrbot.com/
Apache License 2.0
30 stars 20 forks source link

YouTube simulcast support #1503

Open mrphlip opened 1 year ago

mrphlip commented 1 year ago

Brainstorming what would be good for the chatbot to have, should LRR decide to go ahead with the youtube simulcast thing...

mrphlip commented 1 year ago

Implementation brainstorming:

We already have the ability to bold external message sources into the IRC-client backend... for Twitch whispers, we have some processing to make it so incoming whispers are fed into the backend as private messages, and then any private messages the bot sends are turned into outgoing whispers before they're sent. So we know this is possible.

So we could do something similar to integrate YT... have the bot connect to the YT chat, and feed any messages received into the IRC-client backend as though they were messages in, say, the #youtube channel, and then any outgoing messages to that channel can be intercepted and sent back to the current YT chat?

andreasots commented 1 year ago

My notes going through YT's API documentation:

  • Ability to talk to YT's chat API
  • Read messages

LiveChatMessages: list and LiveChatMessages: insert

  • Automatically detect when they're streaming on YT, and join the chat

There doesn't seem to be a concept of joining. Basically you have to somehow find a chat ID and then start fetching messages.

There's LiveBroadcasts: list with mine=true but it would need the broadcaster's OAuth token. The chat ID is items[].snippet.liveChatId.

Alternative the Discord bot currently does this:

From the last step we could get the chat ID from items[].liveStreamingDetails.activeLiveChatId

There's also PubSubHubbub but I'm choosing to ignore it because it's XML.

  • Does YT chat have some equivalent of "whispers" we want to hook into?

I don't think so.

  • Recognising YT members for sub-only commands, and YT mods for mod-only commands

This is in the authorDetails of the chat message:

  • Log new subscribers, memberships, superchats, for notifications

I believe it's impossible to get subscribers in that direction (there is no 'who is subscribed to me' request, only 'who am I subscribed to'). I think the rest is in the chat message. BTW: members used to be called sponsors and the API hasn't been updated to reflect that.

  • Log moderator actions to Slack

There is a snippet.userBannedDetails on the chat message. The author of the message is the moderator.

Implementation:

  • allow cross-linking of Twitch users and YT users
  • allow users to log in to lrrbot.com with their YT account, instead of their Twitch account?

I think this needs a radical new concept of a user without a Twitch account. We should look around for Flask extensions that could do most of the account and auth stuff for us. I found Flask-Dance but maybe there's something even better.

I considered doing it for Patreon but I decided not to do it because we still had votes and I didn't know what to do with those when merging users together when linking.

converting YT chat into IRC

The channel name should contain the chat ID because I suspect there can be multiple active chats at a time, for example between streams the old chat is still active after a stream for a bit but also a new stream has started. Also the channel name schema should be such that if it accidentally gets sent to Twitch then Twitch would reject it. So maybe something like &youtube:LIVE_CHAT_ID.

I don't know what to do with the lack of direct messaging. Although if we do nothing and just discard them then the experience would be pretty much the same as on Twitch where whisper delivery is basically guaranteed to not happen because of default permissions. (By default whispers from strangers are blocked and moderators in a chat where you just advertised your viewbotting service are considered strangers.)

paul-lrr commented 9 months ago

As an update on LRR youtube stuff, a priority would be to get youtube members integrated into LRRbot for sub welcomes. Not only because we want to thank those people, but also because we want to use "get a shout out on the stream" as the required youtube membership perk.

Looking at the youtube API docs, there is an endpoint for listing the current youtube members (https://developers.google.com/youtube/v3/docs/members/list). Unfortunately, there isn't a notification system for new members, but the list endpoint does have an updates mode which looks like it is intended to be polled to find new members. Alternatively, even if we were only able to pull the full list into LRRbot, we could do something where we thank the whole youtube list at the same time, once a month, during LoadingReadyLive or something like that.

andreasots commented 8 months ago

New events that will be added soon™:

"youtube-membership"

A user has become a channel member. Almost the same structure as "twitch-subscription". Counts toward the combined storm count.

Normal version:

{
    "time": str,
    "name": str,
    "channel_id": str, // user's channel ID
    "avatar": str,
    "tier": Optional[str], // membership level name
    "is_upgrade": bool, // whether the user just upgraded from a lower level
    "count": int,
}

Gift version:

{
    "time": str,
    "name": str,
    "channel_id": str, // user's channel ID
    "avatar": str,
    "benefactor": str,
    "tier": Optional[str],
    "ismulti": bool, // whether this event is part of a multi-gift drop
    "count": int,
}

"youtube-membership-milestone"

A user has sent a Membership Milestone Chat. Almost the same structure as "twitch-resubscription". Counts toward the combined storm count.

{
    "time": str,
    "name": str,
    "channel_id": str, // user's channel ID
    "avatar": str,
    "tier": Optional[str],
    "monthcount": int,
    "message": str,
    "count": str,
}

"youtube-membership-gift"

A user has gifted one or more memberships. Almost the same structure as "twitch-subscription-mysterygift". Unlike "twitch-subscription-mysterygift" it gets sent for even a single gift membership.

{
    "time": str,
    "name": str,
    "channel_id": str, // user's channel ID
    "avatar": str,
    "count": int, // NB! this is the number of memberships gifted and not a storm count
    "tier": Optional[str], // membership level name
    "members": List[YoutubeMembership], // list of `"youtube-membership"` payloads (the gift version) without `"time"`
}

"youtube-super-chat"

A user has sent a Super Chat.

{
    "time": str,
    "name": str, // user's channel name
    "channel_id": str, // user's channel ID    
    "avatar": str, // user's avatar
    "amount": str, // amount paid (e.g "$1.00" for a 1 USD Super Chat)
    "amount_micros": int, // amount paid in micros of the purchase currency (e.g 1000000 for a 1 USD Super Chat)
    "amount_currency": str, // ISO 4217 code for the purchase currency (e.g USD)
    "level": int, // Super Chat tier based on the money spent
    "message": str, // user's message
    "count": int, // storm count
}

"youtube-super-sticker"

A user has sent a Super Sticker.

{
    "time": str,
    "name": str, // user's channel name
    "channel_id": str, // user's channel ID
    "avatar": str, // user's avatar
    "amount": str, // amount paid
    "amount_micros": int, // amount paid in micros of the purchase currency
    "amount_currency": str // ISO 4217 code for the purchase currency
    "level": str, // Super Sticker tier based on the money spent
    "sticker_id": str, // ID of the sticker
    "sticker_url": Optional[str], // URL for the sticker image
    "alt_text": str, // the sticker's alt text
    "alt_text_language": str, // the BCP 47 tag for the language the alt text is in
    "count": // storm count
}

EDIT: added "sticker_url" to youtube-super-sticker.

andreasots commented 8 months ago

I've merged and deployed the initial version of LRRbot's YouTube integration.

Changes:

Roadmap:

  1. Create notifications for members who joined outside a stream. LRR needs to contact their YouTube rep to get us access to Members: list.
  2. Implement chat commands.
  3. Implement spam filters.
  4. Implement the chat log.
paul-lrr commented 8 months ago

wow, this looks great! It is so nice to have LRRbot integrating and normalizing the notifications from the different systems instead of having to build all that functionality into each overlay or widget that I make. Do you need anything from me to put this into production? Not sure if LRRbot needs to be given special permissions on the LRR Youtube account or something. Also, will these Youtube membership start showing up on the LRRbot.com/notifications page?

andreasots commented 8 months ago

I've added a fallback for getting active streams without LRR's token and enabled joining YouTube chats in LRRbot.

Also, will these Youtube membership start showing up on the LRRbot.com/notifications page?

Yes. notifications page

paul-lrr commented 8 months ago

A couple of questions: With the above update, does that mean that you don't need an LRR login token to get new/recurring memberships, superchat, etc? Does this get the info when LRR isn't streaming to youtube?

andreasots commented 8 months ago

With the above update, does that mean that you don't need an LRR login token to get new/recurring memberships, superchat, etc?

The only thing that the fallback changes is how LRRbot discovers streams. With the fallback LRRbot will join the chat when the stream goes public. With LRR's token LRRbot would join the chat when the stream is created.

Or rather up to five minutes later because LRRbot checks streams every five minutes.

Does this get the info when LRR isn't streaming to youtube?

No. Fetching members outside of a stream with Members: list requires LRR's token and also LRR to contact their YouTube rep to give us access.